home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CreatingGames / Utilities / Misc / AHI / Developer / drivers / paula / paula_audio.a < prev    next >
Encoding:
Text File  |  1997-10-08  |  82.1 KB  |  3,758 lines

  1. *** ScR ***
  2.  
  3. *** NOTES ***
  4.  
  5. *  The sampler routines are just for fun. Since interrupts must not be disabled,
  6. * there are lots of clicks.
  7.  
  8. ;------------
  9.  
  10. VERSION        EQU    4
  11. REVISION    EQU    14
  12. DATE    MACRO
  13.         dc.b    "20.8.97"
  14.     ENDM
  15. VERS    MACRO
  16.         dc.b    "paula.audio 4.14"
  17.     ENDM
  18. VSTRING    MACRO
  19.         VERS
  20.         dc.b    " ("
  21.         DATE
  22.         dc.b    ")",13,10,0
  23.     ENDM
  24. VERSTAG    MACRO
  25.         dc.b    0,"$VER: "
  26.         VERS
  27.         dc.b    " ("
  28.         DATE
  29.         dc.b    ")",0
  30.     ENDM
  31.  
  32.     incdir    include:
  33.  
  34.     include    hardware/all.i
  35.  
  36.     include    devices/audio.i
  37.     include    dos/dos.i
  38.     include    exec/exec.i
  39.     include    graphics/gfxbase.i
  40.     include intuition/intuitionbase.i
  41.     include intuition/screens.i
  42.     include    resources/misc.i
  43.     include    resources/card.i
  44.     include    utility/utility.i
  45.     include    utility/hooks.i
  46.  
  47.     include    lvo/cardres_lib.i
  48.     include    lvo/dos_lib.i
  49.     include    lvo/exec_lib.i
  50.     include    lvo/graphics_lib.i
  51.     include    lvo/intuition_lib.i
  52.     include    lvo/utility_lib.i
  53.  
  54.     include    devices/ahi.i
  55.     include    libraries/ahi_sub.i
  56.     include    lvo/ahi_sub_lib.i
  57.  
  58.     include    macros.i
  59.  
  60. DEBUG_DETAIL    SET    0
  61.  
  62. _ciaa        EQU    $bfe001
  63. _ciab        EQU    $bfd000
  64.  
  65. PALFREQ        EQU    3546895
  66. NTSCFREQ    EQU    3579545
  67. MINPER        EQU    62
  68.  
  69. RECORDSAMPLES    EQU    1024
  70.  
  71.  
  72. * paula.audio extra tags
  73. AHIDB_Paula14Bit    EQU    AHIDB_UserBase+0    * Boolean
  74. AHIDB_PaulaTable    EQU    AHIDB_UserBase+1    * Boolean
  75.  
  76.  * paulaBase (private)
  77.     STRUCTURE paulaBase,LIB_SIZE
  78.     UBYTE    pb_Flags
  79.     UBYTE    pb_Pad1
  80.     UWORD    pb_Pad2
  81.     APTR    pb_SysLib
  82.     ULONG    pb_SegList
  83.     APTR    pb_GfxLib
  84.     APTR    pb_UtilLib
  85.     APTR    pb_DosLib
  86.     APTR    pb_IntuiLib
  87.     APTR    pb_MiscResource
  88.     APTR    pb_CardResource
  89.     LABEL    paulaBase_SIZEOF
  90.  
  91.  * paula (private) ahiac_DriverData points to this structure.
  92.     STRUCTURE paula,0
  93.     UBYTE    p_Flags
  94.     UBYTE    p_Parallel            ;TRUE if parport allocated
  95.     UWORD    p_DisableCount            ;AHIsub_Enable/AHIsub_Disable cnt
  96.  
  97.     ULONG    p_MinBufferLength
  98.     APTR    p_DMAbuffer            ;Chipmem play buffer
  99.     APTR    p_CalibrationTable
  100.  
  101.     ULONG    p_DoubleBufferOffset
  102.  
  103.     UWORD    p_SwapChannels
  104.     UWORD    p_Pad1
  105.  
  106. ; Pointers to chipmem play buffer
  107.  
  108.     LABEL    p_AudPtrs
  109.     APTR    p_AudPtr1A
  110.     APTR    p_AudPtr2A
  111.     APTR    p_AudPtr3A
  112.     APTR    p_AudPtr4A
  113.     APTR    p_AudPtr1B
  114.     APTR    p_AudPtr2B
  115.     APTR    p_AudPtr3B
  116.     APTR    p_AudPtr4B
  117.  
  118.     UWORD    p_AudPer
  119.     UWORD    p_OutputVolume
  120.     UWORD    p_MonitorVolume
  121.     UWORD    p_Input
  122.  
  123.     APTR    p_AudioCtrl
  124.  
  125.     APTR    p_audioport
  126.     APTR    p_audioreq
  127.     ULONG    p_audiodev
  128.     APTR    p_ParBitsUser
  129.     APTR    p_ParPortUser
  130.     APTR    p_SerBitsUser
  131.     APTR    p_CardHandle
  132.  
  133.     STRUCT    p_PlayInt,IS_SIZE
  134.     STRUCT    p_PlaySoftInt,IS_SIZE
  135.     STRUCT    p_RecInt,IS_SIZE
  136.     STRUCT    p_RecSoftInt,IS_SIZE
  137.  
  138.     ULONG    p_LoopTimes
  139.  
  140.     LABEL    p_PlayerHookRegs
  141.     APTR    p_PlayerHook
  142.     ULONG    p_Reserved
  143.     FPTR    p_PlayerEntry            ;p_PlayerHook->h_Entry
  144.  
  145.     LABEL    p_MixHookRegs
  146.     APTR    p_MixHook
  147.     APTR    p_Mixbuffer
  148.     FPTR    p_MixEntry            ;p_MixHook->h_Entry
  149.  
  150.     LABEL    p_RecIntDataAura
  151.     APTR    p_AuraAddress
  152.  
  153.     LABEL    p_RecIntData
  154.     APTR    p_RecFillPtr
  155.     UWORD    p_RecFillCount
  156.     UWORD    p_Pad2
  157.     APTR    p_RecBuffer1
  158.     APTR    p_RecBuffer2
  159.     APTR    p_RecSoftIntPtr
  160.  
  161.     LABEL    p_RecordMessage
  162.     ULONG    p_rmType
  163.     APTR    p_rmBuffer
  164.     ULONG    p_rmLength
  165.  
  166.     STRUCT    p_CalibrationArray,256
  167.     LABEL    paula_SIZEOF
  168.  
  169. * p_Flags
  170.     BITDEF    P,14BIT,0
  171.     BITDEF    P,HIFI,1
  172. PB_STEREO    EQU    AHIACB_STEREO        ;=2
  173. PF_STEREO    EQU    AHIACF_STEREO
  174.  
  175. Start:
  176.     moveq    #-1,d0
  177.     rts
  178.  
  179. RomTag:
  180.     DC.W    RTC_MATCHWORD
  181.     DC.L    RomTag
  182.     DC.L    EndCode
  183.     DC.B    RTF_AUTOINIT
  184.     DC.B    VERSION                ;version
  185.     DC.B    NT_LIBRARY
  186.     DC.B    0                ;pri
  187.     DC.L    LibName
  188.     DC.L    IDString
  189.     DC.L    InitTable
  190.  
  191. LibName:    dc.b    "paula.audio",0
  192. IDString:    VSTRING
  193. gfxName:    GRAPHICSNAME
  194. utilName:    UTILITYNAME
  195. dosName:    DOSNAME
  196. intuiName:    dc.b    "intuition.library",0
  197. miscName:    MISCNAME
  198. cardName:    dc.b    "card.resource",0
  199. filterVar:    dc.b    "AHIpaulaFilterFreq",0
  200. screenVar:    dc.b    "AHIpaulaSampleLimit",0
  201. bufferVar:    dc.b    "AHIpaulaBufferLength",0
  202. swapVar:    dc.b    "AHIpaulaSwapChannels",0
  203.     cnop    0,2
  204.  
  205. InitTable:
  206.     DC.L    paulaBase_SIZEOF
  207.     DC.L    funcTable
  208.     DC.L    dataTable
  209.     DC.L    initRoutine
  210.  
  211. funcTable:
  212.     dc.l    Open
  213.     dc.l    Close
  214.     dc.l    Expunge
  215.     dc.l    Null
  216. *
  217.     dc.l    AHIsub_AllocAudio
  218.     dc.l    AHIsub_FreeAudio
  219.     dc.l    AHIsub_Disable
  220.     dc.l    AHIsub_Enable
  221.     dc.l    AHIsub_Start
  222.     dc.l    AHIsub_Update
  223.     dc.l    AHIsub_Stop
  224.     dc.l    AHIsub_SetVol
  225.     dc.l    AHIsub_SetFreq
  226.     dc.l    AHIsub_SetSound
  227.     dc.l    AHIsub_SetEffect
  228.     dc.l    AHIsub_LoadSound
  229.     dc.l    AHIsub_UnloadSound
  230.     dc.l    AHIsub_GetAttr
  231.     dc.l    AHIsub_HardwareControl
  232.     dc.l    -1
  233.  
  234. dataTable:
  235.     INITBYTE    LN_TYPE,NT_LIBRARY
  236.     INITLONG    LN_NAME,LibName
  237.     INITBYTE    LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  238.     INITWORD    LIB_VERSION,VERSION
  239.     INITWORD    LIB_REVISION,REVISION
  240.     INITLONG    LIB_IDSTRING,IDString
  241.     DC.L        0
  242.  
  243. initRoutine:
  244.     movem.l    d1/a0/a1/a5/a6,-(sp)
  245.     move.l    d0,a5
  246.     move.l    a6,pb_SysLib(a5)
  247.     move.l    a0,pb_SegList(a5)
  248.     lea    gfxName(pc),a1
  249.     moveq    #0,d0
  250.     call    OpenLibrary
  251.     move.l    d0,pb_GfxLib(a5)
  252.     bne.b    .gfxOK
  253.     ALERT    AG_OpenLib|AO_GraphicsLib
  254.     moveq    #0,d0
  255.     bra    .exit
  256. .gfxOK
  257.     lea    utilName(pc),a1
  258.     moveq    #0,d0
  259.     call    OpenLibrary
  260.     move.l    d0,pb_UtilLib(a5)
  261.     bne.b    .utilOK
  262.     ALERT    AG_OpenLib|AO_UtilityLib
  263.     moveq    #0,d0
  264.     bra    .exit
  265. .utilOK
  266.     lea    dosName(pc),a1
  267.     moveq    #0,d0
  268.     call    OpenLibrary
  269.     move.l    d0,pb_DosLib(a5)
  270.     bne.b    .dosOK
  271.     ALERT    AG_OpenLib|AO_DOSLib
  272.     moveq    #0,d0
  273.     bra    .exit
  274. .dosOK
  275.     lea    intuiName(pc),a1
  276.     moveq    #0,d0
  277.     call    OpenLibrary
  278.     move.l    d0,pb_IntuiLib(a5)
  279.     bne.b    .intuiOK
  280.     ALERT    AG_OpenLib|AO_Intuition
  281.     moveq    #0,d0
  282.     bra    .exit
  283. .intuiOK
  284.     lea    miscName(pc),a1
  285.     call    OpenResource
  286.     move.l    d0,pb_MiscResource(a5)
  287.     bne.b    .miscOK
  288.     ALERT    AG_OpenRes|AO_MiscRsrc
  289.     moveq    #0,d0
  290.     bra    .exit
  291. .miscOK
  292.     lea    cardName(pc),a1
  293.     call    OpenResource
  294.     move.l    d0,pb_CardResource(a5)        ;Don't fail on error
  295.  
  296.     move.l    a5,d0
  297. .exit
  298.     movem.l    (sp)+,d1/a0/a1/a5/a6
  299.     rts
  300.  
  301. Open:
  302.     moveq    #0,d0
  303.     addq.w    #1,LIB_OPENCNT(a6)
  304.     bclr.b    #LIBB_DELEXP,pb_Flags(a6)
  305.     move.l    a6,d0
  306. .exit
  307.     rts
  308.  
  309. Close:
  310.     moveq    #0,d0
  311.     subq.w    #1,LIB_OPENCNT(a6)
  312.     bne.b    .exit
  313.     btst.b    #LIBB_DELEXP,pb_Flags(a6)
  314.     beq.b    .exit
  315.     bsr    Expunge
  316. .exit
  317.     rts
  318.  
  319. Expunge:
  320.     movem.l    d1/d2/a0/a1/a5/a6,-(sp)
  321.     move.l    a6,a5
  322.     move.l    pb_SysLib(a5),a6
  323.     tst.w    LIB_OPENCNT(a5)
  324.     beq.b    .notopen
  325.     bset.b    #LIBB_DELEXP,pb_Flags(a5)
  326.     moveq    #0,d0
  327.     bra.b    .Expunge_end
  328. .notopen
  329.     move.l    pb_IntuiLib(a5),a1
  330.     call    CloseLibrary
  331.  
  332.     move.l    pb_DosLib(a5),a1
  333.     call    CloseLibrary
  334.  
  335.     move.l    pb_UtilLib(a5),a1
  336.     call    CloseLibrary
  337.  
  338.     move.l    pb_GfxLib(a5),a1
  339.     call    CloseLibrary
  340.  
  341.     move.l    pb_SegList(a5),d2
  342.     move.l    a5,a1
  343.     call    Remove
  344.  
  345.     moveq    #0,d0
  346.     move.l    a5,a1
  347.     move.w    LIB_NEGSIZE(a5),d0
  348.     sub.l    d0,a1
  349.     add.w    LIB_POSSIZE(a5),d0
  350.     call    FreeMem
  351.     move.l    d2,d0
  352. .Expunge_end
  353.     movem.l    (sp)+,d1/d2/a0/a1/a5/a6
  354.     rts
  355.  
  356. Null:
  357.     moveq    #0,d0
  358.     rts
  359.  
  360. * BeginIO(ioRequest)(a1) (From amiga.lib)
  361. BeginIO:
  362.     move.l    a1,a0        ;probably not neccesary
  363.     push    a6
  364.     move.l    IO_DEVICE(a1),a6
  365.     jsr    -30(a6)
  366.     pop    a6
  367.     rts
  368.  
  369. ****** [driver].audio/--background-- ****************************************
  370. *
  371. *   OVERVIEW
  372. *
  373. *       DRIVER VERSIONS
  374. *
  375. *       The lowest supported driver version is 2. If you use any feature
  376. *       introduced in later versions of AHI, you should set the driver
  377. *       version to the same version as the features were introduced with.
  378. *       Example: You use PreTimer() and PostTimer(), and since these
  379. *       calls were added in V4 of ahi.device, your driver's version should
  380. *       be 4, too.
  381. *
  382. *       AUDIO ID NUMBERS
  383. *
  384. *       Just some notes about selecting ID numbers for different modes:
  385. *       It is up to the driver programmer to chose which modes should be
  386. *       available to the user. Take care when selecting.
  387. *
  388. *       The upper word is the hardware ID, and can only be allocated by
  389. *       Martin Blom <lcs@lysator.liu.se>. The lower word is free, but in
  390. *       order to allow enhancements, please only use bit 0 to 3 for modes!
  391. *       If your driver supports multiple sound cards, use bit 12-15 to
  392. *       select card (first one is 0). If your sound card has multiple
  393. *       AD/DA converters, you can use bit 8-11 to select them (the first
  394. *       should be 0).
  395. *
  396. *       Set the remaining bits to zero.
  397. *
  398. *       Use AHI:Developer/Support/ScanAudioModes to have a look at the modes
  399. *       currently available. Use AHI:Developer/Support/sift to make sure your
  400. *       mode descriptor file is a legal IFF file.
  401. *
  402. *       I do reserve the right to change the rules if I find them incorrect!
  403. *
  404. *****************************************************************************
  405. *
  406. *
  407.  
  408. ****** [driver].audio/AHIsub_AllocAudio *************************************
  409. *
  410. *   NAME
  411. *       AHIsub_AllocAudio -- Allocates and initializes the audio hardware.
  412. *
  413. *   SYNOPSIS
  414. *       result = AHIsub_AllocAudio( tags, audioctrl);
  415. *       D0                          A1    A2
  416. *
  417. *       ULONG AHIsub_AllocAudio( struct TagItem *, struct AHIAudioCtrlDrv * );
  418. *
  419. *   IMPLEMENTATION
  420. *       Allocate and initialize the audio hardware. Decide if and how you
  421. *       wish to use the mixing routines provided by 'ahi.device', by looking
  422. *       in the AHIAudioCtrlDrv structure and parsing the tag list for tags
  423. *       you support.
  424. *
  425. *       1) Use mixing routines with timing:
  426. *           You will need to be able to play any number of samples from
  427. *           about 80 up to 65535 with low overhead.
  428. *           · Update AudioCtrl->ahiac_MixFreq to nearest value that your
  429. *             hardware supports.
  430. *           · Return AHISF_MIXING|AHISF_TIMING.
  431. *       2) Use mixing routines without timing:
  432. *           If the hardware can't play samples with any length, use this
  433. *           alternative and provide timing yourself. The buffer must
  434. *           take less than about 20 ms to play, preferable less than 10!
  435. *           · Update AudioCtrl->ahiac_MixFreq to nearest value that your
  436. *             hardware supports.
  437. *           · Store the number of samples to mix each pass in
  438. *             AudioCtrl->ahiac_BuffSamples.
  439. *           · Return AHISF_MIXING
  440. *           Alternatively, you can use the first method and call the
  441. *           mixing hook several times in a row to fill up a buffer.
  442. *           In that case, AHIsub_GetAttr(AHIDB_MaxPlaySamples) should
  443. *           return the size of the buffer plus AudioCtrl->ahiac_MaxBuffSamples.
  444. *           If the buffer is so large that it takes more than (approx.) 10 ms to
  445. *           play it for high sample frequencies, AHIsub_GetAttr(AHIDB_Realtime)
  446. *           should return FALSE.
  447. *       3) Don't use mixing routines:
  448. *           If your hardware can handle everything without using the CPU to
  449. *           mix the channels, you tell 'ahi.device' this by not setting
  450. *           either the AHISB_MIXING or the AHISB_TIMING bit.
  451. *
  452. *       If you can handle stereo output from the mixing routines, also set
  453. *       bit AHISB_KNOWSTEREO.
  454. *
  455. *       If you can handle hifi (32 bit) output from the mixing routines,
  456. *       set bit AHISB_KNOWHIFI.
  457. *
  458. *       If this driver can be used to record samples, set bit AHISB_CANRECORD,
  459. *       too (regardless if you use the mixing routines in AHI or not).
  460. *
  461. *       If the sound card has hardware to do DSP effects, you can set the
  462. *       AHISB_CANPOSTPROCESS bit. The output from the mixing routines will 
  463. *       then be two separate buffers, one wet and one dry. You should then
  464. *       apply the Fx on the wet buffer, and post-mix the two buffers before
  465. *       you send the samples to the DAC. (V4)
  466. *
  467. *   INPUTS
  468. *       tags - pointer to a taglist.
  469. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  470. *
  471. *   TAGS
  472. *       The tags are from the audio database (AHIDB_#? in <devices/ahi.h>),
  473. *       NOT the tag list the user called ahi.device/AHI_AllocAudio() with.
  474. *
  475. *   RESULT
  476. *       Flags, defined in <libraries/ahi_sub.h>.
  477. *
  478. *   EXAMPLE
  479. *
  480. *   NOTES
  481. *       You don't have to clean up on failure, AHIsub_FreeAudio() will
  482. *       always be called.
  483. *
  484. *   BUGS
  485. *
  486. *   SEE ALSO
  487. *       AHIsub_FreeAudio(), AHIsub_Start()
  488. *
  489. *****************************************************************************
  490. *
  491. *
  492.  
  493. AHIsub_AllocAudio:
  494.     pushm    d2-d7/a2-a6
  495.     move.l    a6,a5
  496.  
  497.     move.l    a1,d3
  498.  
  499. * Allocate the 'paula' structure (our variables)
  500.     move.l    pb_SysLib(a5),a6
  501.     move.l    #paula_SIZEOF,d0
  502.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  503.     call    AllocVec
  504.     move.l    d0,ahiac_DriverData(a2)
  505.     beq    .error_nopaula
  506.     move.l    d0,a3
  507.  
  508. * Initialize some fields...
  509.     move.l    #-1,p_audiodev(a3)
  510.     move.l    #-1,p_ParBitsUser(a3)
  511.     move.l    #-1,p_ParPortUser(a3)
  512.     move.l    #-1,p_SerBitsUser(a3)
  513.     move.l    a2,p_AudioCtrl(a3)
  514.     lea    p_RecSoftInt(a3),a0
  515.     move.l    a0,p_RecSoftIntPtr(a3)
  516.     move.l    #AHIST_S16S,p_rmType(a3)
  517.     move.l    #RECORDSAMPLES,p_rmLength(a3)
  518.     move.w    #64,p_OutputVolume(a3)
  519.  
  520. * Translate tags to flags
  521.     moveq    #0,d2
  522.     move.l    pb_UtilLib(a5),a6
  523.     move.l    #AHIDB_Paula14Bit,d0
  524.     moveq    #0,d1
  525.     move.l    d3,a0                ;tag list
  526.     call    GetTagData
  527.     tst.l    d0
  528.     beq.b    .no14bit
  529.     moveq    #PF_14BIT,d2
  530. .no14bit
  531.     move.l    #AHIDB_HiFi,d0
  532.     moveq    #0,d1
  533.     move.l    d3,a0                ;tag list
  534.     call    GetTagData
  535.     tst.l    d0
  536.     beq.b    .noHiFi
  537.     or.b    #PF_HIFI,d2
  538. .noHiFi
  539.     move.l    ahiac_Flags(a2),d0
  540.     and.b    #PF_STEREO,d0            ;same as AHIACF_STEREO
  541.     or.b    d2,d0
  542.     move.b    p_Flags(a3),d1
  543.     and.b    #~(PF_STEREO|PF_HIFI|PF_14BIT),d1
  544.     or.b    d0,d1
  545.     move.b    d1,p_Flags(a3)
  546.  
  547. * Check if a table should be used (14 bit calibration)
  548.     move.l    #AHIDB_PaulaTable,d0
  549.     moveq    #0,d1
  550.     move.l    d3,a0                ;tag list
  551.     call    GetTagData
  552.     tst.l    d0
  553.     beq    .notable
  554.  
  555. * Load 'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
  556. * and initialize the table.
  557. * FIXIT: The calibration file should move to a special chunk in
  558. * 'DEVS:AudioModes/PAULA'.
  559.     move.l    pb_DosLib(a5),a6
  560.     lea    .calibname(pc),a0
  561.     move.l    a0,d1
  562.     move.l    #MODE_OLDFILE,d2
  563.     call    Open
  564.     move.l    d0,d4
  565.     beq    .nocalib
  566.     move.l    d0,d1
  567.     lea    p_CalibrationArray(a3),a0
  568.     move.l    a0,d2
  569.     move.l    #256,d3
  570.     call    Read
  571.     cmp.l    d0,d3
  572.     beq    .tableloaded
  573. .nocalib
  574. ; Fill defaults
  575.     lea    p_CalibrationArray(a3),a0
  576.     move.w    #254-1,d0
  577. .initcalib
  578.     move.b    #$55,(a0)+
  579.     dbf    d0,.initcalib
  580.     move.b    #$7f,(a0)+
  581. .tableloaded
  582.     move.l    d4,d1
  583.     beq.b    .nofile
  584.     call    Close
  585. .nofile
  586.     move.l    pb_SysLib(a5),a6
  587.     move.l    #65536*2,d0
  588.     move.l    #MEMF_PUBLIC,d1
  589.     call    AllocVec
  590.     move.l    d0,p_CalibrationTable(a3)
  591.     beq.b    .notable
  592.     move.l    d0,a0            ;table
  593.     lea    p_CalibrationArray(a3),a1
  594.     bsr.w    _CreateTable
  595. .notable
  596.  
  597. * Get the minimum chip buffer size
  598.     moveq    #0,d5                ;Default
  599.     move.l    pb_DosLib(a5),a6
  600.     subq.l    #8,sp                ;local label
  601.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  602.     lea    bufferVar(pc),a0
  603.     move.l    a0,d1
  604.     move.l    sp,d2
  605.     moveq.l    #8,d3
  606.     moveq.l    #0,d4
  607.     call    GetVar
  608.     cmp.l    #-1,d0
  609.     beq    .gotlength
  610.     move.l    sp,d1
  611.     pea.l    0.w
  612.     move.l    sp,d2
  613.     call    StrToLong
  614.     move.l    (sp)+,d5
  615. .gotlength
  616.     addq.l    #8,sp
  617. ; d5 is now the buffer length
  618.     move.l    d5,p_MinBufferLength(a3)
  619.  
  620. * Check if we should swap left & right channels
  621.     moveq    #0,d5                ;Default
  622.     move.l    pb_DosLib(a5),a6
  623.     subq.l    #8,sp                ;local label
  624.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  625.     lea    swapVar(pc),a0
  626.     move.l    a0,d1
  627.     move.l    sp,d2
  628.     moveq.l    #8,d3
  629.     moveq.l    #0,d4
  630.     call    GetVar
  631.     cmp.l    #-1,d0
  632.     beq    .gotswap
  633.     move.l    sp,d1
  634.     pea.l    0.w
  635.     move.l    sp,d2
  636.     call    StrToLong
  637.     move.l    (sp)+,d5
  638. .gotswap
  639.     addq.l    #8,sp
  640. ; d5 is now the buffer length
  641.     move.w    d5,p_SwapChannels(a3)
  642.  
  643. * allocate audio.device
  644.     move.l    pb_SysLib(a5),a6
  645.     call    CreateMsgPort
  646.     move.l    d0,p_audioport(a3)
  647.     beq    .error_noport
  648.     moveq    #ioa_SIZEOF,d0
  649.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  650.     call    AllocVec
  651.     move.l    d0,p_audioreq(a3)
  652.     beq    .error_noreqmem
  653.     move.l    d0,a0
  654.     move.l    p_audioport(a3),MN_REPLYPORT(a0)
  655.     clr.w    ioa_AllocKey(a0)
  656.     move.b    #127,LN_PRI(a0)            ;steal it!
  657.     lea    .audiochannelarray(pc),a1
  658.     move.l    a1,ioa_Data(a0)
  659.     move.l    #1,ioa_Length(a0)
  660.     lea    .audioname(pc),a0
  661.     moveq    #0,d0
  662.     move.l    p_audioreq(a3),a1
  663.     moveq    #0,d1
  664.     call    OpenDevice
  665.     move.l    d0,p_audiodev(a3)
  666.     bne    .error_noaudiodev        ;somebody already owns the hardware (could be us!)
  667.     move.l    p_audioreq(a3),a1
  668.     move.w    #CMD_RESET,IO_COMMAND(a1)
  669.     bsr.w    BeginIO                ;clear attach, stop sound.
  670.     move.l    p_audioport(a3),a0
  671.     call    WaitPort
  672.     move.l    p_audioport(a3),a0
  673.     call    GetMsg
  674.  
  675.     move.l    pb_DosLib(a5),a6
  676.     moveq    #1,d1
  677.     call    Delay
  678.  
  679. * test if mode supports recording
  680.     btst    #PB_14BIT,p_Flags(a3)
  681.     bne    .dontgetsampler            ;no record if 14 bit mode
  682.  
  683. * try to allocate parallel port
  684.     clr.b    p_Parallel(a3)
  685.     move.l    pb_MiscResource(a5),a6
  686.     moveq    #MR_PARALLELBITS,d0
  687.     lea    IDString(pc),a1
  688.     jsr    MR_ALLOCMISCRESOURCE(a6)
  689.     move.l    d0,p_ParBitsUser(a3)
  690.     bne    .no_parrallel
  691.     moveq    #MR_PARALLELPORT,d0
  692.     lea    IDString(pc),a1
  693.     jsr    MR_ALLOCMISCRESOURCE(a6)
  694.     move.l    d0,p_ParPortUser(a3)
  695.     bne    .no_parrallel
  696.  
  697.     move.b    #TRUE,p_Parallel(a3)
  698.     move.b    #0,_ciaa+ciaddrb            ;make PB0-PB7 inputs
  699. .no_parrallel
  700.  
  701. * allocate Aura sampler
  702.     clr.l    p_AuraAddress(a3)
  703.     move.l    pb_CardResource(a5),d0
  704.     beq    .no_aura
  705.     move.l    d0,a6
  706.     call    GetCardMap
  707.     tst.l    d0
  708.     beq    .no_aura
  709.     move.l    d0,a0
  710.     move.l    cmm_IOMemory(a0),d2
  711.     beq    .no_aura
  712.  
  713.     move.l    pb_SysLib(a5),a6
  714.     moveq    #CardHandle_SIZEOF,d0
  715.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  716.     call    AllocVec
  717.     move.l    d0,p_CardHandle(a3)
  718.     beq    .no_aura
  719.  
  720.     move.l    pb_CardResource(a5),a6
  721.     move.l    d0,a1
  722.     move.l    #IDString,LN_NAME(a1)
  723.     move.b    #CARDF_RESETREMOVE|CARDF_IFAVAILABLE,cah_CardFlags(a1)
  724.     call    OwnCard
  725.     tst.l    d0
  726.     bne    .no_aura
  727.  
  728.     move.l    p_CardHandle(a3),a1
  729.     call    BeginCardAccess
  730.  
  731.     move.l    d2,p_AuraAddress(a3)
  732. .no_aura
  733. .dontgetsampler
  734.  
  735.  
  736. * initialize interrupts (Only dummy function pointers at this time)
  737.  
  738.  * p_PlayInt (the main playback interrupt)
  739.     move.b    #NT_INTERRUPT,LN_TYPE+p_PlayInt(a3)
  740.     move.l    #LibName,LN_NAME+p_PlayInt(a3)
  741.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  742.     move.l    a3,IS_DATA+p_PlayInt(a3)
  743.  
  744.  * p_PlaySoftInt (caused by p_PlayInt, here are the mixing and conversion done)
  745.     move.b    #NT_INTERRUPT,LN_TYPE+p_PlaySoftInt(a3)
  746.     move.l    #LibName,LN_NAME+p_PlaySoftInt(a3)
  747.     move.l    #SoftInt_Dummy,IS_CODE+p_PlaySoftInt(a3)
  748.     move.l    a3,IS_DATA+p_PlaySoftInt(a3)
  749.  
  750.  * p_RecInt (the interrupt used for recording)
  751.     move.b    #NT_INTERRUPT,LN_TYPE+p_RecInt(a3)
  752.     move.l    #LibName,LN_NAME+p_RecInt(a3)
  753.     move.l    #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
  754.     clr.l    IS_DATA+p_RecInt(a3)
  755.  
  756.  * p_RecSoftInt (caused by p_RecInt when the record buffer has been filled)
  757.     move.b    #32,LN_PRI+p_RecSoftInt(a3)
  758.     move.b    #NT_INTERRUPT,LN_TYPE+p_RecSoftInt(a3)
  759.     move.l    #LibName,LN_NAME+p_RecSoftInt(a3)
  760.     move.l    #RecordSoftInt,IS_CODE+p_RecSoftInt(a3)
  761.     move.l    a3,IS_DATA+p_RecSoftInt(a3)
  762.  
  763. * Make sure no interrupts occur until AHIsub_Start() is called
  764.     move.w    #INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3,custom+INTENA
  765.  
  766. * Update ahiac_MixFreq to what the mixing/sampling frequency really is
  767.     move.l    ahiac_MixFreq(a2),d1
  768.     bsr    calcperiod
  769.     move.l    d0,ahiac_MixFreq(a2)        ;store actual freq
  770.  
  771. * Check the AHIpaulaFilterFreq variable.
  772. * If the mixing frequency is higher than this one, set disable the filter,
  773. * else enable it.
  774.     moveq    #0,d5                ;Default freq
  775.     move.l    pb_DosLib(a5),a6
  776.     subq.l    #8,sp                ;local label
  777.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  778.     lea    filterVar(pc),a0
  779.     move.l    a0,d1
  780.     move.l    sp,d2
  781.     moveq.l    #8,d3
  782.     moveq.l    #0,d4
  783.     call    GetVar
  784.     cmp.l    #-1,d0
  785.     beq    .gotfreq
  786.     move.l    sp,d1
  787.     pea.l    0.w
  788.     move.l    sp,d2
  789.     call    StrToLong
  790.     move.l    (sp)+,d5
  791. .gotfreq
  792.     addq.l    #8,sp
  793. ; d5 is now the freq
  794.  
  795.     cmp.l    ahiac_MixFreq(a2),d5
  796.     bls    .no_filter
  797.     bclr    #1,$bfe001            ;turn audio filter on
  798.     bra    .filter_set
  799. .no_filter
  800.     bset    #1,$bfe001            ;turn audio filter off
  801. .filter_set
  802.  
  803.     moveq    #AHISF_KNOWSTEREO|AHISF_KNOWHIFI|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING,d0
  804. .exit
  805.     popm    d2-d7/a2-a6
  806.     rts
  807.  
  808. .error_noaudiodev
  809. .error_noreqmem
  810. .error_noport
  811. .error_nopaula
  812.     moveq    #AHISF_ERROR,d0
  813.     bra.b    .exit
  814.  
  815. .audiochannelarray
  816.     dc.b    1+2+4+8
  817. .audioname
  818.     AUDIONAME
  819. .calibname
  820.     dc.b    "ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
  821.     even
  822. .cardhandle:
  823.     dc.l    0,0        ;ln_Succ, ln_Pred
  824.     dc.b    0        ;ln_Type
  825.     dc.b    0        ;ln_Pri
  826.     dc.l    IDString    ;ln_Name
  827.     dc.l    0,0,0        ;cah_CardRemoved, cah_CardInserted, cah_CardStatus
  828.     dc.b    (CARDF_RESETREMOVE|CARDF_IFAVAILABLE)
  829.     even
  830.  
  831. ;in:
  832. * d1    MixFreq
  833. * a5    paulaBase
  834. ;out:
  835. * d0    New MixFreq
  836. * d1.w    Period
  837. ;description:
  838. *    Calculate and return the best period and the actual frequency.
  839. calcperiod:
  840.     pushm    d2-d7/a2-a6
  841.     move.l    #PALFREQ,d2            ;PAL
  842.     move.l    pb_GfxLib(a5),a0
  843.     move.w    gb_DisplayFlags(a0),d0
  844.     btst    #REALLY_PALn,d0
  845.     bne.b    .1
  846.     move.l    #NTSCFREQ,d2            ;NTSC
  847. .1
  848.     move.l    d2,d0
  849.     move.l    d1,d3
  850.     move.l    pb_UtilLib(a5),a1
  851.     jsr    _LVOUDivMod32(a1)
  852.     lsl.l    #1,d1
  853.     cmp.l    d3,d1
  854.     bmi.b    .3
  855.     addq.l    #1,d0
  856. .3
  857.     move.w    d0,d4
  858. * d4 is now period. Check if is it a valid one, depending on current display mode
  859.     bsr    checkvideo
  860.     moveq    #MINPER,d1
  861.     tst.l    d0
  862.     bne    .5
  863.     moveq    #MINPER*2,d1
  864. .5
  865.     cmp.w    d1,d4
  866.     bhs.b    .6
  867.     move.w    d1,d4
  868. .6
  869.     moveq    #0,d1
  870.     move.w    d4,d1
  871.     move.l    d2,d0
  872.     move.l    d1,d3
  873.     move.l    pb_UtilLib(a5),a1
  874.     jsr    _LVOUDivMod32(a1)
  875.     lsl.l    #1,d1
  876.     cmp.l    d3,d1
  877.     bmi.b    .4
  878.     addq.l    #1,d0
  879. .4
  880.     move.w    d4,d1
  881.     popm    d2-d7/a2-a6
  882.     rts
  883.  
  884. ;in:
  885. * a5    paulaBase
  886. ;out:
  887. * d0    TRUE if current mode is double
  888. ;description:
  889. *    Checks if the current screen mode is doublescan.
  890. *    This routine is a bit ugly, but it does get the job
  891. *    done, even if a graphic card is used.
  892. checkvideo:
  893.     pushm    d2-d7/a2-a6
  894.  
  895. * Check the AHIpaulaSampleLimit variable.
  896. * If 1, allow > 28 kHz frequencies, if 0, don't. If not present,
  897. * check the screen mode.
  898.     move.l    pb_DosLib(a5),a6
  899.     clr.w    -(sp)                ;Initialize local data
  900.     lea    screenVar(pc),a0
  901.     move.l    a0,d1
  902.     move.l    sp,d2
  903.     moveq.l    #2,d3
  904.     moveq.l    #0,d4
  905.     call    GetVar
  906.     move.w    (sp)+,d1
  907.     cmp.l    #-1,d0
  908.     beq    .testfreq
  909.     cmp.w    #"0"<<8|0,d1
  910.     beq    .no31k
  911.     cmp.w    #"1"<<8|0,d1
  912.     beq    .is31k
  913.  
  914. .testfreq
  915.  
  916. ; Chip revision test
  917.  
  918.     move.l    pb_GfxLib(a5),a0
  919.     move.b    gb_ChipRevBits0(a0),d0
  920.     and.b    #GFXF_HR_DENISE|GFXF_AA_LISA,d0
  921.     beq    .no31k                ; OCS: No 31 kHz modes
  922.  
  923. ; Native screen test
  924.  
  925.     moveq    #0,d0
  926.     move.l    pb_IntuiLib(a5),a6
  927.     call    LockIBase
  928.     move.l    d0,d2
  929.     move.l    ib_FirstScreen(a6),a0
  930.     lea    sc_ViewPort(a0),a0
  931.     move.l    pb_GfxLib(a5),a6
  932.     call    GetVPModeID
  933.     move.l    d2,a0
  934.     move.l    d0,d2
  935.     move.l    pb_IntuiLib(a5),a6
  936.     call    UnlockIBase
  937.  
  938.     ; "Check" if native screen
  939.     move.l    d2,d0
  940.     and.l    #$40000000,d0
  941.     bne    .gfxcard
  942.  
  943.     ; It is!
  944.     sub.w    #mtr_SIZEOF,sp            ;local storage
  945.     suba.l    a0,a0
  946.     move.l    sp,a1
  947.     move.l    #mtr_SIZEOF,d0
  948.     move.l    #DTAG_MNTR,d1
  949.     move.l    pb_GfxLib(a5),a6
  950.     call    GetDisplayInfoData
  951.  
  952.     moveq    #1,d1
  953.     add.w    mtr_TotalRows(sp),d1
  954.     sub.w    mtr_MinRow(sp),d1
  955.     move.w    mtr_TotalColorClocks(sp),d2
  956.     mulu.w    mtr_TotalRows(sp),d2
  957.  
  958.     add.w    #mtr_SIZEOF,sp            ;restore stack
  959.     tst.l    d0
  960.     beq    .no31k
  961.     ; Calculate TotalColorClocks*TotalRows/(2*(TotalRows-MinRow+1)
  962.     add.l    d1,d1
  963.     beq    .no31k
  964.     divu    d1,d2
  965.     cmp.w    #64,d2                ; 64 is an round nice number, no?
  966.     bls    .is31k
  967.     bra    .no31k
  968.  
  969. .gfxcard
  970.  
  971. ; Picasso '96 test
  972.  
  973.     move.l    pb_SysLib(a5),a6
  974.     lea    .picasso96(pc),a1
  975.     call    Forbid                ; Not required, it's just to...
  976.     call    FindTask
  977.     call    Permit                ; ...make PatchWork happy.
  978.     tst.l    d0
  979.     beq    .cgfx                ; Not P96, assume CyberGraphX
  980.  
  981.     move.l    pb_DosLib(a5),a6
  982.     clr.l    -(sp)                ;Initialize local data
  983.     lea    .p96amigavideo(pc),a0
  984.     move.l    a0,d1
  985.     move.l    sp,d2
  986.     moveq.l    #4,d3
  987.     moveq.l    #0,d4
  988.     call    GetVar
  989.     move.l    (sp)+,d1
  990.     swap.w    d1
  991.     cmp.w    #"31",d1
  992.     beq    .is31k
  993.     bra    .no31k
  994.  
  995. .cgfx
  996.  
  997. ; CybergraphX test
  998.  
  999.     move.l    pb_GfxLib(a5),a0
  1000.     cmp.w    #39,LIB_VERSION(a0)
  1001.     beq    .known
  1002.     cmp.w    #40,LIB_VERSION(a0)
  1003.     beq    .known
  1004.     bra    .no31k
  1005. .known
  1006.     move.l    gb_copinit(a0),a0
  1007.     cmp.w    #$01FC,copinit_fm0(a0)        ;Security check (test if really FMODE)
  1008.     bne    .is31k                ;Probably an ECS machine.
  1009.                         ;Assume the user is clever enough
  1010.                         ;to use "AddAudioModes DBLSCAN"....
  1011.     move.w    copinit_fm0+2(a0),d0
  1012.     and.w    #$c000,d0            ;Mask sprite and bitplane double bit
  1013.     beq    .no31k
  1014. .is31k
  1015.     moveq    #TRUE,d0
  1016.     bra    .exit
  1017. .no31k
  1018.     moveq    #FALSE,d0
  1019. .exit
  1020.     popm    d2-d7/a2-a6
  1021.     rts
  1022. .picasso96
  1023.     dc.b    "Picasso96",0
  1024. .p96amigavideo
  1025.     dc.b    "Picasso96/AmigaVideo",0
  1026.     even
  1027.  
  1028. ;in:
  1029. * d0    Frequency
  1030. ;out:
  1031. * d0    Closest frequency
  1032. * d1    Index
  1033. findfreq:
  1034.     lea    freqlist(pc),a0
  1035.     cmp.l    (a0),d0
  1036.     bls.b    .2
  1037. .findfreq
  1038.     cmp.l    (a0)+,d0
  1039.     bhi.b    .findfreq
  1040.     move.l    -4(a0),d1
  1041.     sub.l    d0,d1
  1042.     sub.l    -8(a0),d0
  1043.     cmp.l    d1,d0
  1044.     bhs.b    .1
  1045.     subq.l    #4,a0
  1046. .1
  1047.     subq.l    #4,a0
  1048. .2
  1049.     move.l    (a0),d0
  1050.     move.l    a0,d1
  1051.     sub.l    #freqlist,d1
  1052.     lsr.l    #2,d1
  1053.     rts
  1054.  
  1055. freqlist:
  1056.     dc.l    4410                    ; CD/10
  1057.     dc.l    4800                    ; DAT/10
  1058.     dc.l    5513                    ; CD/8
  1059.     dc.l    6000                    ; DAT/8
  1060.     dc.l    7350                    ; CD/6
  1061.     dc.l    8000                    ; µ- and A-Law, DAT/6
  1062.     dc.l    9600                    ; DAT/5
  1063.     dc.l    11025                    ; CD/4
  1064.     dc.l    12000                    ; DAT/4
  1065.     dc.l    14700                    ; CD/3
  1066.     dc.l    16000                    ; DAT/3
  1067.     dc.l    17640                    ; CD/2.5
  1068.     dc.l    18900
  1069.     dc.l    19200                    ; DAT/2.5
  1070.     dc.l    22050                    ; CD/2
  1071.     dc.l    24000                    ; DAT/2
  1072.     dc.l    27429
  1073. FREQUENCIES_OCS        EQU    (*-freqlist)>>2
  1074.     dc.l    29400                    ; CD/1.5
  1075.     dc.l    32000                    ; DAT/1.5
  1076.     dc.l    33075
  1077.     dc.l    37800
  1078.     dc.l    44100                    ; CD
  1079.     dc.l    48000                    ; DAT
  1080. FREQUENCIES        EQU    (*-freqlist)>>2
  1081.     dc.l    -1
  1082.  
  1083. * _CreateTable directly stolen from Christian Buchner's CyberSound
  1084. * audio sub system (with permission).
  1085.  
  1086. * _CreateTable **************************************************************
  1087.  
  1088.         ; Parameters
  1089.  
  1090.         ; a0 = Table address
  1091.         ; (MUST have enough space for 65536 UWORDS)
  1092.         ; a1 = Additive Array
  1093.         ; 256 UBYTEs
  1094.         ;
  1095.         ; the table is organized as follows:
  1096.         ; 32768 UWORDS positive range, ascending order
  1097.         ; 32768 UWORDS negative range, ascending order
  1098.         ; access: (a0,d0.l*2)
  1099.         ; where d0.w is signed word sample data
  1100.         ; and the upper word of d0.l is *cleared!*
  1101.  
  1102.  
  1103. _CreateTable    movem.l    a2/d2-d6,-(sp)
  1104.  
  1105.         lea    128(a1),a2
  1106.  
  1107.         move.l    a2,a1            ; count the number of steps
  1108.         moveq    #128-1,d0        ; in the positive range
  1109.         moveq    #0,d5
  1110. .countpositive    move.b    (a1)+,d1
  1111.         ext.w    d1
  1112.         ext.l    d1
  1113.         add.l    d1,d5
  1114.         dbra    d0,.countpositive    ; d5=number of steps
  1115.         move.l    #32768,d6        ; reset stretch counter
  1116.  
  1117.         move.l    a2,a1            ; middle value in calibdata
  1118.         move.w    #32768-1,d0        ; number of positive values -1
  1119.         moveq    #0,d1            ; HI value
  1120.         moveq    #0,d2            ; LO value
  1121.         moveq    #0,d3            ; counter
  1122. .fetchnext2    move.b    (a1)+,d4        ; add calibtable to counter
  1123.         ext.w    d4
  1124.         add.w    d4,d3
  1125. .outerloop2    tst.w    d3
  1126.         bgt.s    .positive2
  1127. .negative2    addq.w    #1,d1            ; increment HI value
  1128.         sub.w    d4,d2            ; reset LO value
  1129.         bra.s    .fetchnext2
  1130. .positive2    move.b    d1,(a0)+        ; store HI and LO value
  1131.         move.b    d2,(a0)+
  1132.         sub.l    d5,d6            ; stretch the table
  1133.         bpl.s    .repeat2        ; to 32768 entries
  1134.         add.l    #32768,d6
  1135.         addq.w    #1,d2            ; increment LO value
  1136.         subq.w    #1,d3            ; decrement counter
  1137. .repeat2    dbra    d0,.outerloop2
  1138.  
  1139.         move.l    a2,a1            ; count the number of steps
  1140.         moveq    #128-1,d0        ; in the negative range
  1141.         moveq    #0,d5
  1142. .countnegative    move.b    -(a1),d1
  1143.         ext.w    d1
  1144.         ext.l    d1
  1145.         add.l    d1,d5
  1146.         dbra    d0,.countnegative    ; d5=number of steps
  1147.         move.l    #32768,d6        ; reset stretch counter
  1148.  
  1149.         add.l    #2*32768,a0        ; place at the end of the table
  1150.         move.l    a2,a1            ; middle value in calibdata
  1151.         move.w    #32768-1,d0        ; number of negative values -1
  1152.         moveq    #-1,d1            ; HI value
  1153.         moveq    #-1,d2            ; LO value
  1154.         moveq    #0,d3            ; counter
  1155. .fetchnext1    move.b    -(a1),d4        ; add calibtable to counter
  1156.         ext.w    d4
  1157.         add.w    d4,d3
  1158.         add.w    d4,d2            ; maximize LO value
  1159. .outerloop1    tst.w    d3
  1160.         bgt.s    .positive1
  1161. .negative1    subq.w    #1,d1
  1162.         bra.s    .fetchnext1
  1163. .positive1    move.b    d2,-(a0)        ; store LO and HI value
  1164.         move.b    d1,-(a0)
  1165.         sub.l    d5,d6            ; stretch the table
  1166.         bpl.s    .repeat1        ; to 32768 entries
  1167.         add.l    #32768,d6
  1168.         subq.w    #1,d2            ; decrement lo value
  1169.         subq.w    #1,d3            ; decrement counter
  1170. .repeat1    dbra    d0,.outerloop1
  1171.  
  1172.         movem.l    (sp)+,a2/d2-d6
  1173.         rts
  1174.  
  1175.  
  1176. ****** [driver].audio/AHIsub_FreeAudio **************************************
  1177. *
  1178. *   NAME
  1179. *       AHIsub_FreeAudio -- Deallocates the audio hardware.
  1180. *
  1181. *   SYNOPSIS
  1182. *       AHIsub_FreeAudio( audioctrl );
  1183. *                         A2
  1184. *
  1185. *       void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
  1186. *
  1187. *   IMPLEMENTATION
  1188. *       Deallocate the audio hardware and other resources allocated in
  1189. *       AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
  1190. *       'ahi.device' before this call is made.
  1191. *
  1192. *   INPUTS
  1193. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1194. *
  1195. *   NOTES
  1196. *       It must be safe to call this routine even if AHIsub_AllocAudio()
  1197. *       was never called, failed or called more than once.
  1198. *
  1199. *   SEE ALSO
  1200. *       AHIsub_AllocAudio()
  1201. *
  1202. *****************************************************************************
  1203. *
  1204. *
  1205.  
  1206. AHIsub_FreeAudio:
  1207.     pushm    d2-d7/a2-a6
  1208.  
  1209.     move.l    a6,a5
  1210.     move.l    pb_SysLib(a5),a6
  1211.  
  1212.     move.l    ahiac_DriverData(a2),d0
  1213.     beq    .nopaula
  1214.     move.l    d0,a3
  1215.  
  1216.     move.l    p_CalibrationTable(a3),d0
  1217.     beq.b    .notable
  1218.     move.l    d0,a1
  1219.     call    FreeVec
  1220. .notable
  1221.     tst.l    p_audiodev(a3)
  1222.     bne.b    .noaudiodev
  1223.     move.l    p_audioreq(a3),a1
  1224.     move.w    #CMD_RESET,IO_COMMAND(a1)    ;Restore audio interrupts
  1225.     bsr.w    BeginIO
  1226.     move.l    p_audioport(a3),a0
  1227.     call    WaitPort
  1228.     move.l    p_audioport(a3),a0
  1229.     call    GetMsg
  1230.     move.l    p_audioreq(a3),a1
  1231.     subq.l    #1,p_audiodev(a3)
  1232.     call    CloseDevice
  1233. .noaudiodev
  1234.     move.l    p_audioreq(a3),d0
  1235.     beq.b    .noaudioreq
  1236.     move.l    d0,a1
  1237.     call    FreeVec
  1238. .noaudioreq
  1239.     move.l    p_audioport(a3),d0
  1240.     beq.b    .noaudioport
  1241.     move.l    d0,a0
  1242.     call    DeleteMsgPort
  1243. .noaudioport
  1244.     tst.l    p_AuraAddress(a3)
  1245.     beq    .noaura
  1246.     move.l    pb_CardResource(a5),d0
  1247.     beq    .noaura
  1248.     move.l    d0,a6
  1249.     move.l    p_CardHandle(a3),d0
  1250.     beq    .noaura
  1251.     move.l    d0,a1
  1252.     call    EndCardAccess
  1253.     move.l    p_CardHandle(a3),a1
  1254.     moveq    #CARDF_REMOVEHANDLE,d0
  1255.     call    ReleaseCard
  1256. .noaura
  1257.     move.l    pb_SysLib(a5),a6
  1258.     move.l    p_CardHandle(a3),d0
  1259.     beq    .nocardhandle
  1260.     move.l    d0,a1
  1261.     call    FreeVec
  1262. .nocardhandle
  1263.     move.l    pb_MiscResource(a5),a6
  1264.     tst.l    p_ParPortUser(a3)
  1265.     bne.b    .noparport
  1266.     moveq    #MR_PARALLELPORT,d0
  1267.     jsr    MR_FREEMISCRESOURCE(a6)
  1268. .noparport
  1269.     tst.l    p_ParBitsUser(a3)
  1270.     bne.b    .noparbits
  1271.     moveq    #MR_PARALLELBITS,d0
  1272.     jsr    MR_FREEMISCRESOURCE(a6)
  1273. .noparbits
  1274.     tst.l    p_SerBitsUser(a3)
  1275.     bne.b    .noserbits
  1276.     moveq    #MR_SERIALBITS,d0
  1277.     jsr    MR_FREEMISCRESOURCE(a6)
  1278. .noserbits
  1279.     move.l    pb_SysLib(a5),a6
  1280.     move.l    a3,a1
  1281.     clr.l    ahiac_DriverData(a2)
  1282.     call    FreeVec
  1283. .nopaula
  1284.     moveq    #0,d0
  1285.     popm    d2-d7/a2-a6
  1286.     rts
  1287.  
  1288.  
  1289. ****** [driver].audio/AHIsub_Disable ****************************************
  1290. *
  1291. *   NAME
  1292. *       AHIsub_Disable -- Temporary turn off audio interrupt/task
  1293. *
  1294. *   SYNOPSIS
  1295. *       AHIsub_Disable( audioctrl );
  1296. *                       A2
  1297. *
  1298. *       void AHIsub_Disable( struct AHIAudioCtrlDrv * );
  1299. *
  1300. *   IMPLEMENTATION
  1301. *       If you are lazy, then call exec.library/Disable().
  1302. *       If you are smart, only disable your own interrupt or task.
  1303. *
  1304. *   INPUTS
  1305. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1306. *
  1307. *   NOTES
  1308. *       This call should be guaranteed to preserve all registers.
  1309. *       This call nests.
  1310. *
  1311. *   SEE ALSO
  1312. *       AHIsub_Enable(), exec.library/Disable()
  1313. *
  1314. *****************************************************************************
  1315. *
  1316. *
  1317.  
  1318. AHIsub_Disable:
  1319.     push    a3
  1320.     move.l    ahiac_DriverData(a2),a3
  1321.     addq.w    #1,p_DisableCount(a3)
  1322.     move.w    #INTF_AUD0,custom+INTENA
  1323.     pop    a3
  1324.     rts
  1325.  
  1326. ****** [driver].audio/AHIsub_Enable *****************************************
  1327. *
  1328. *   NAME
  1329. *       AHIsub_Enable -- Turn on audio interrupt/task
  1330. *
  1331. *   SYNOPSIS
  1332. *       AHIsub_Enable( audioctrl );
  1333. *                      A2
  1334. *
  1335. *       void AHIsub_Enable( struct AHIAudioCtrlDrv * );
  1336. *
  1337. *   IMPLEMENTATION
  1338. *       If you are lazy, then call exec.library/Enable().
  1339. *       If you are smart, only enable your own interrupt or task.
  1340. *
  1341. *   INPUTS
  1342. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1343. *
  1344. *   NOTES
  1345. *       This call should be guaranteed to preserve all registers.
  1346. *       This call nests.
  1347. *
  1348. *   SEE ALSO
  1349. *       AHIsub_Disable(), exec.library/Enable()
  1350. *
  1351. *****************************************************************************
  1352. *
  1353. *
  1354.  
  1355. AHIsub_Enable:
  1356.     push    a3
  1357.     move.l    ahiac_DriverData(a2),a3
  1358.     subq.w    #1,p_DisableCount(a3)
  1359.     bne.b    .exit
  1360.     move.w    #INTF_SETCLR|INTF_AUD0,custom+INTENA
  1361. .exit
  1362.     pop    a3
  1363.     rts
  1364.  
  1365. ****** [driver].audio/AHIsub_Start ******************************************
  1366. *
  1367. *   NAME
  1368. *       AHIsub_Start -- Starts playback or recording
  1369. *
  1370. *   SYNOPSIS
  1371. *       error = AHIsub_Start( flags, audioctrl );
  1372. *       D0                    D0     A2
  1373. *
  1374. *       ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
  1375. *
  1376. *   IMPLEMENTATION
  1377. *       What to do depends what you returned in AHIsub_AllocAudio().
  1378. *
  1379. *     * First, assume bit AHISB_PLAY in flags is set. This means that you
  1380. *       should begin playback.
  1381. *
  1382. *     - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
  1383. *
  1384. *       A) Allocate a mixing buffer of ahiac_BuffSize bytes. The buffer must
  1385. *          be long aligned!
  1386. *       B) Create/start an interrupt or task that will do 1-6 over and over
  1387. *          again until AHIsub_Stop() is called. Note that it is not a good
  1388. *          idea to do the actual mixing and conversion in a real hardware
  1389. *          interrupt. Signal a task or create a Software Interrupt to do
  1390. *          the number crunching.
  1391. *
  1392. *       1) Call the user Hook ahiac_PlayerFunc with the following parameters:
  1393. *                  A0 - (struct Hook *)
  1394. *                  A2 - (struct AHIAudioCtrlDrv *)
  1395. *                  A1 - Set to NULL.
  1396. *
  1397. *       2) [Call the ahiac_PreTimer function. If it returns TRUE (Z will be
  1398. *          cleared so you don't have to test d0), skip step 3 and 4. This
  1399. *          is used to avoid overloading the CPU. This step is optional.
  1400. *          A2 is assumed to point to struct AHIAudioCtrlDrv. All registers
  1401. *          except d0 are preserved.  (V4)]
  1402. *
  1403. *       3) Call the mixing Hook (ahiac_MixerFunc) with the following
  1404. *          parameters:
  1405. *                  A0 - (struct Hook *)           - The Hook itself
  1406. *                  A2 - (struct AHIAudioCtrlDrv *)
  1407. *                  A1 - (WORD *[])                - The mixing buffer.
  1408. *          Note that ahiac_MixerFunc preserves ALL registers.
  1409. *          The user Hook ahiac_SoundFunc will be called by the mixing
  1410. *          routine when a sample have been processed, so you don't have to
  1411. *          worry about that.
  1412. *          How the buffer will be filled is indicated by ahiac_Flags.
  1413. *          It is always filled with signed 16-bit (32 bit if AHIACB_HIFI in
  1414. *          in ahiac_Flags is set) words, even if playback is 8 bit. If
  1415. *          AHIDBB_STEREO is set (in ahiac_Flags), data for left and right
  1416. *          channel are interleaved:
  1417. *           1st sample left channel,
  1418. *           1st sample right channel,
  1419. *           2nd sample left channel,
  1420. *           ...,
  1421. *           ahiac_BuffSamples:th sample left channel,
  1422. *           ahiac_BuffSamples:th sample right channel.
  1423. *          If AHIDBB_STEREO is cleared, the mono data is stored:
  1424. *           1st sample,
  1425. *           2nd sample,
  1426. *           ...,
  1427. *           ahiac_BuffSamples:th sample.
  1428. *          Note that neither AHIACB_STEREO nor AHIACB_HIFI will be set if
  1429. *          you didn't report that you understand these flags when
  1430. *          AHI_AllocAudio() was called.
  1431. *
  1432. *          For AHI V2, the type of buffer is also available in ahiac_BuffType.
  1433. *          It is suggested that you use this value instead. ahiac_BuffType
  1434. *          can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S and AHIST_S32S.
  1435. *
  1436. *       4) Convert the buffer if needed and feed it to the audio hardware.
  1437. *          Note that you may have to clear CPU caches if you are using DMA
  1438. *          to play the buffer, and the buffer is not allocated in non-
  1439. *          cachable RAM.
  1440. *
  1441. *       5) [Call the ahiac_PostTimer function. A2 is assumed to point to
  1442. *          struct AHIAudioCtrlDrv. All registers are preserved.  (V4)]
  1443. *
  1444. *       6) Wait until the whole buffer has been played, then repeat.
  1445. *
  1446. *       Use double buffering if possible!
  1447. *
  1448. *       You may DECREASE ahiac_BuffSamples slightly, for example to force an
  1449. *       even number of samples to be mixed. By doing this you will make
  1450. *       ahiac_PlayerFunc to be called at wrong frequency so be careful!
  1451. *       Even if ahiac_BuffSamples is defined ULONG, it will never be greater
  1452. *       than 65535.
  1453. *
  1454. *       ahiac_BuffSize is the largest size of the mixing buffer that will be
  1455. *       needed until AHIsub_Stop() is called.
  1456. *
  1457. *       ahiac_MaxBuffSamples is the maximum number of samples that will be
  1458. *       mixed (until AHIsub_Stop() is called). You can use this value if you
  1459. *       need to allocate DMA buffers.
  1460. *
  1461. *       ahiac_MinBuffSamples is the minimum number of samples that will be
  1462. *       mixed. Most drivers will ignore it.
  1463. *
  1464. *       If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
  1465. *       ahiac_BuffSize is large enough to hold two buffers. The mixing buffer
  1466. *       will be filled with the wet buffer first, immediately followed by the
  1467. *       dry buffer. I.e., ahiac_BuffSamples sample frames wet data, then
  1468. *       ahiac_BuffSamples sample frames dry data. The DSP fx should only be
  1469. *       applied to the wet buffer, and the two buffers should then be added
  1470. *       together. (V4)
  1471. *
  1472. *     - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
  1473. *       except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
  1474. *       ahiac_PlayerFreq times per second, clocked by timers on your sound
  1475. *       card or by using 'realtime.library'. No other Amiga resources may
  1476. *       be used for timing (like direct CIA timers).
  1477. *       ahiac_MinBuffSamples and ahiac_MaxBuffSamples are undefined if
  1478. *       AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit not set).
  1479. *
  1480. *     - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
  1481. *       the AHISB_TIMING bit set, then just start playback. Don't forget to
  1482. *       call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
  1483. *       own timing hardware or 'realtime.library' may be used. Note that
  1484. *       ahiac_MixerFunc, ahiac_BuffSamples, ahiac_MinBuffSamples,
  1485. *       ahiac_MaxBuffSamples and ahiac_BuffSize are undefined. ahiac_MixFreq
  1486. *       is the frequency the user wants to use for recording, if you support
  1487. *       that.
  1488. *
  1489. *     * Second, assume bit AHISB_RECORD in flags is set. This means that you
  1490. *       should start to sample. Create a interrupt or task that does the
  1491. *       following:
  1492. *
  1493. *       Allocate a buffer (you chose size, but try to keep it reasonable
  1494. *       small to avoid delays - it is suggested that RecordFunc is called
  1495. *       at least 4 times/second for the lowers sampling rate, and more often
  1496. *       for higher rates), and fill it with the sampled data. The buffer must
  1497. *       be long aligned, and it's size must be evenly divisible by four.
  1498. *       The format should always be AHIST_S16S (even with 8 bit mono samplers),
  1499. *       which means:
  1500. *           1st sample left channel,
  1501. *           1st sample right channel (same as prev. if mono),
  1502. *           2nd sample left channel,
  1503. *           ... etc.
  1504. *       Each sample is a signed word (WORD). The sample rate should be equal
  1505. *       to the mixing rate.
  1506. *
  1507. *       Call the ahiac_SamplerFunc Hook with the following parameters:
  1508. *           A0 - (struct Hook *)           - The Hook itself
  1509. *           A2 - (struct AHIAudioCtrlDrv *)
  1510. *           A1 - (struct AHIRecordMessage *)
  1511. *       The message should be filled as follows:
  1512. *           ahirm_Type - Set to AHIST_S16S.
  1513. *           ahirm_Buffer - A pointer to the filled buffer.
  1514. *           ahirm_Samples - How many sample frames stored.
  1515. *       You must not destroy the buffer until next time the Hook is called.
  1516. *
  1517. *       Repeat until AHIsub_Stop() is called.
  1518. *
  1519. *     * Note that both bits may be set when this function is called.
  1520. *
  1521. *   INPUTS
  1522. *       flags - See <libraries/ahi_sub.h>.
  1523. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1524. *
  1525. *   RESULT
  1526. *       Returns AHIE_OK if successful, else an error code as defined
  1527. *       in <devices/ahi.h>. AHIsub_Stop() will always be called, even
  1528. *       if this call failed.
  1529. *
  1530. *   NOTES
  1531. *       The driver must be able to handle multiple calls to this routine
  1532. *       without preceding calls to AHIsub_Stop().
  1533. *
  1534. *   SEE ALSO
  1535. *       AHIsub_Update(), AHIsub_Stop()
  1536. *
  1537. *****************************************************************************
  1538. *
  1539. *
  1540. *
  1541.  
  1542. AHIsub_Start:
  1543.     pushm    d2-d7/a2-a6
  1544.  
  1545.     move.l    d0,d7
  1546.     lea    custom,a4
  1547.     move.l    ahiac_DriverData(a2),a3
  1548.  
  1549.     btst    #AHISB_PLAY,d7
  1550.     beq    .dont_play
  1551.  
  1552. **
  1553. *** AHISB_PLAY
  1554. **
  1555.     moveq    #AHISF_PLAY,d0
  1556.     call    AHIsub_Stop            ;Stop current playback if any.
  1557.     call    AHIsub_Update            ;fill variables
  1558.  
  1559.     move.l    a6,a5
  1560.     move.l    pb_SysLib(a5),a6
  1561.  
  1562.     move.l    ahiac_BuffSize(a2),d0
  1563.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  1564.     call    AllocVec
  1565.     move.l    d0,p_Mixbuffer(a3)
  1566.     beq    .error_nomem
  1567.  
  1568.     move.l    ahiac_MixFreq(a2),d1
  1569.     bsr.w    calcperiod
  1570.     move.w    d1,p_AudPer(a3)
  1571.  
  1572. * The init*bit?  routines allocates p_DMAbuffer, sets up
  1573. * p_AudPtr, sets the volume, stores the correct interrupt routines in
  1574. * p_PlayInt's and p_PlaySoftInt's IS_CODE.
  1575.  
  1576.     pea    .1(pc)
  1577.     move.b    p_Flags(a3),d0
  1578.     and.b    #PF_STEREO|PF_14BIT,d0
  1579.     beq.w    init8bitM
  1580.     cmp.b    #PF_STEREO,d0
  1581.     beq.w    init8bitS
  1582.     cmp.b    #PF_14BIT,d0
  1583.     beq.w    init14bitM
  1584.     bra.w    init14bitS
  1585. .1
  1586.     tst.l    d0
  1587.     bne    .exit
  1588.  
  1589. * Install play interrupt
  1590.     lea    p_PlayInt(a3),a1
  1591.     moveq    #INTB_AUD0,d0
  1592.     call    SetIntVector
  1593.     clr.w    p_DisableCount(a3)
  1594.  
  1595.     move.w    #INTF_SETCLR|INTF_AUD0,INTENA(a4)    ;enable
  1596.     move.w    #INTF_SETCLR|INTF_AUD0,INTREQ(a4)    ;start
  1597.  
  1598.     move.l    a5,a6
  1599.  
  1600.  
  1601. .dont_play
  1602.     btst    #AHISB_RECORD,d7
  1603.     beq    .dont_record
  1604. **
  1605. *** AHISB_RECORD
  1606. **
  1607.     btst    #PB_14BIT,p_Flags(a3)        ;Sanity check...
  1608.     bne    .error_unknown
  1609.  
  1610.     moveq    #AHISF_RECORD,d0
  1611.     call    AHIsub_Stop            ;Stop current recording if any.
  1612.  
  1613.     move.l    a6,a5
  1614.     move.l    pb_SysLib(a5),a6
  1615.  
  1616.     move.l    #RECORDSAMPLES*4,d0
  1617.     move.l    #MEMF_PUBLIC,d1
  1618.     call    AllocVec
  1619.     move.l    d0,p_RecBuffer1(a3)
  1620.     beq    .error_nomem
  1621.  
  1622.     move.l    d0,p_RecFillPtr(a3)
  1623.     move.w    #RECORDSAMPLES,p_RecFillCount(a3)
  1624.  
  1625.     move.l    #RECORDSAMPLES*4,d0
  1626.     move.l    #MEMF_PUBLIC,d1
  1627.     call    AllocVec
  1628.     move.l    d0,p_RecBuffer2(a3)
  1629.     beq    .error_nomem
  1630.  
  1631.     move.l    ahiac_MixFreq(a2),d1
  1632.     bsr.w    calcperiod
  1633.     lsr.w    #1,d1                ;Period/2 => Frequency·2
  1634.     move.w    d1,AUD2PER(a4)
  1635.     move.w    d1,AUD3PER(a4)
  1636.     move.w    p_MonitorVolume(a3),d0
  1637.     move.w    d0,AUD2VOL(a4)
  1638.     move.w    d0,AUD3VOL(a4)
  1639.  
  1640. * Install record interrupt
  1641.     move.w    p_Input(a3),d0
  1642.     beq    .parsampler
  1643.     cmp.w    #1,d0
  1644.     beq    .aurasampler
  1645.     cmp.w    #2,d0
  1646.     beq    .clarity
  1647.     bra    .error_unknown
  1648.  
  1649. .parsampler
  1650.     tst.b    p_Parallel(a3)            ;Parrallel port allocated?
  1651.     beq    .error_unknown
  1652.     lea    p_RecIntData(a3),a1
  1653.     move.l    a1,IS_DATA+p_RecInt(a3)
  1654.     move.l    #RecordInterrupt,IS_CODE+p_RecInt(a3)
  1655.  
  1656.     move.b    #$ff,_ciab+ciaddrb        ; Set parallel port to output
  1657.  
  1658.     bra    .setrecint
  1659.  
  1660. .clarity
  1661.     tst.b    p_Parallel(a3)            ;Parrallel port allocated?
  1662.     beq    .error_unknown
  1663.  
  1664.     move.l    pb_MiscResource(a5),a6
  1665.     move.l    #MR_SERIALBITS,d0    ; allocate serial port control lines
  1666.     lea    IDString(pc),a1
  1667.     jsr    MR_ALLOCMISCRESOURCE(a6)
  1668.     move.l    d0,p_SerBitsUser(a3)
  1669.     bne    .error_unknown
  1670.  
  1671.     lea    p_RecIntData(a3),a1
  1672.     move.l    a1,IS_DATA+p_RecInt(a3)
  1673.     move.l    #RecordInterruptClarity,IS_CODE+p_RecInt(a3)
  1674.  
  1675.     ; Set DTR, PRTBUSY and PRTRPOUT to outputs
  1676.     or.b    #CIAF_COMDTR!CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciaddra
  1677.     move.b    #$ff,_ciab+ciaddrb        ; Set parallel port to output
  1678.     ; Reset Clarity
  1679.     move.b    #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
  1680.     move.b    #CIAF_PRTRPOUT,_ciab+ciapra
  1681.     move.b    #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
  1682.     ; Clarity is now in stereo record mode
  1683.  
  1684.     bra    .setrecint
  1685.  
  1686. .aurasampler
  1687.     tst.l    p_AuraAddress(a3)        ;Aura sampler allocated?
  1688.     beq    .error_unknown
  1689.     lea    p_RecIntDataAura(a3),a1
  1690.     move.l    a1,IS_DATA+p_RecInt(a3)
  1691.     move.l    #RecordInterruptAura,IS_CODE+p_RecInt(a3)
  1692.     bra    .setrecint
  1693.  
  1694. .setrecint
  1695.     move.l    pb_SysLib(a5),a6
  1696.     lea    p_RecInt(a3),a1
  1697.     moveq    #INTB_AUD3,d0
  1698.     call    SetIntVector
  1699.  
  1700.     move.w    #DMAF_AUD2|DMAF_AUD3,DMACON(a4)        ;disable DMA
  1701.     move.w    #INTF_SETCLR|INTF_AUD3,INTENA(a4)    ;enable
  1702.     move.w    #INTF_SETCLR|INTF_AUD3,INTREQ(a4)    ;start
  1703.  
  1704. .dont_record
  1705. .return
  1706.     moveq    #AHIE_OK,d0
  1707. .exit
  1708.     popm    d2-d7/a2-a6
  1709.     rts
  1710. .error_nomem
  1711.     moveq    #AHIE_NOMEM,d0
  1712.     bra.b    .exit
  1713. .error_unknown
  1714.     moveq    #AHIE_UNKNOWN,d0
  1715.     bra.b    .exit
  1716.  
  1717.  
  1718. ;in:
  1719. * a2    AudioCtrl
  1720. * a3    paula
  1721. * a4    custom
  1722. * a5    paulaBase
  1723. * a6    ExecBase
  1724. init8bitM:
  1725.     PRINTF    2,"init8bitM()"
  1726.     move.l    #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
  1727.     move.l    #SoftInt_8bitM,IS_CODE+p_PlaySoftInt(a3)
  1728.     move.b    p_Flags(a3),d0
  1729.     btst    #PB_HIFI,d0
  1730.     beq    .nohifi
  1731.     move.l    #SoftInt_8bitMH,IS_CODE+p_PlaySoftInt(a3)
  1732. .nohifi
  1733.  
  1734.     move.l    p_MinBufferLength(a3),d0
  1735.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 8 bit samples
  1736.     addq.l    #3,d0
  1737.     and.b    #~3,d0                ;make it a multiple of 4
  1738.     move.l    d0,d2                ;d2 = channel size
  1739.  
  1740.     lsl.l    #1,d0                ;Double buffer
  1741.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1742.     call    AllocVec
  1743.     move.l    d0,p_DMAbuffer(a3)
  1744.     beq    .nomem
  1745.  
  1746.     move.l    d0,p_AudPtr1A(a3)
  1747.     move.l    d0,p_AudPtr2A(a3)
  1748.     add.l    d2,d0
  1749.     move.l    d0,p_AudPtr1B(a3)
  1750.     move.l    d0,p_AudPtr2B(a3)
  1751.  
  1752. ;    move.w    #64,AUD0VOL(a4)
  1753. ;    move.w    #64,AUD1VOL(a4)
  1754.  
  1755.     moveq    #0,d0
  1756.     rts
  1757. .nomem
  1758.     moveq    #AHIE_NOMEM,d0
  1759.     rts
  1760.  
  1761. ;in:
  1762. * a2    AudioCtrl
  1763. * a3    paula
  1764. * a5    paulaBase
  1765. * a6    ExecBase
  1766. init8bitS:
  1767.     PRINTF    2,"init8bitS()"
  1768.     move.l    #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
  1769.     move.l    #SoftInt_8bitS,IS_CODE+p_PlaySoftInt(a3)
  1770.     move.b    p_Flags(a3),d0
  1771.     btst    #PB_HIFI,d0
  1772.     beq    .nohifi
  1773.     move.l    #SoftInt_8bitSH,IS_CODE+p_PlaySoftInt(a3)
  1774. .nohifi
  1775.  
  1776.     move.l    p_MinBufferLength(a3),d0
  1777.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 8 bit samples
  1778.     addq.l    #3,d0
  1779.     and.b    #~3,d0                ;make it a multiple of 4
  1780.     move.l    d0,d2                ;d2 = channel size
  1781.  
  1782.     lsl.l    #2,d0                ;Double buffer + Stereo
  1783.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1784.     call    AllocVec
  1785.     move.l    d0,p_DMAbuffer(a3)
  1786.     beq    .nomem
  1787.  
  1788.     move.l    d0,p_AudPtr1A(a3)
  1789.     add.l    d2,d0
  1790.     move.l    d0,p_AudPtr2A(a3)
  1791.     add.l    d2,d0
  1792.     move.l    d0,p_AudPtr1B(a3)
  1793.     add.l    d2,d0
  1794.     move.l    d0,p_AudPtr2B(a3)
  1795.  
  1796. ;    move.w    #64,AUD0VOL(a4)
  1797. ;    move.w    #64,AUD1VOL(a4)
  1798.  
  1799.     moveq    #0,d0
  1800.     rts
  1801. .nomem
  1802.     moveq    #AHIE_NOMEM,d0
  1803.     rts
  1804.  
  1805. ;in:
  1806. * a2    AudioCtrl
  1807. * a3    paula
  1808. * a5    paulaBase
  1809. * a6    ExecBase
  1810. init14bitM:
  1811.     PRINTF    2,"init14bitM()"
  1812.     move.l    #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
  1813.     lea    SoftInt_14bitM(pc),a0
  1814.     move.b    p_Flags(a3),d0
  1815.     btst    #PB_HIFI,d0
  1816.     beq    .nohifi1
  1817.     lea    SoftInt_14bitMH(pc),a0
  1818. .nohifi1
  1819.     tst.l    p_CalibrationTable(a3)
  1820.     beq.b    .nocalib
  1821.     lea    SoftInt_14CbitM(pc),a0
  1822.     move.b    p_Flags(a3),d0
  1823.     btst    #PB_HIFI,d0
  1824.     beq    .nohifi2
  1825.     lea    SoftInt_14CbitMH(pc),a0
  1826. .nohifi2
  1827. .nocalib
  1828.     move.l    a0,IS_CODE+p_PlaySoftInt(a3)
  1829.  
  1830.     move.l    p_MinBufferLength(a3),d0
  1831.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 16 bit samples
  1832.     addq.l    #3,d0
  1833.     and.b    #~3,d0                ;make it a multiple of 4
  1834.     move.l    d0,d2                ;d2 = channel size
  1835.  
  1836.     lsl.l    #2,d0                ;Double buffer + 2×8 bit
  1837.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1838.     call    AllocVec
  1839.     move.l    d0,p_DMAbuffer(a3)
  1840.     beq    .nomem
  1841.  
  1842.     move.l    d0,p_AudPtr1A(a3)
  1843.     move.l    d0,p_AudPtr2A(a3)
  1844.     add.l    d2,d0
  1845.     move.l    d0,p_AudPtr4A(a3)
  1846.     move.l    d0,p_AudPtr3A(a3)
  1847.     add.l    d2,d0
  1848.     move.l    d0,p_AudPtr1B(a3)
  1849.     move.l    d0,p_AudPtr2B(a3)
  1850.     add.l    d2,d0
  1851.     move.l    d0,p_AudPtr4B(a3)
  1852.     move.l    d0,p_AudPtr3B(a3)
  1853.  
  1854. ;    move.w    #64,AUD0VOL(a4)
  1855. ;    move.w    #64,AUD1VOL(a4)
  1856. ;    move.w    #1,AUD2VOL(a4)
  1857. ;    move.w    #1,AUD3VOL(a4)
  1858.  
  1859.     moveq    #0,d0
  1860.     rts
  1861. .nomem
  1862.     moveq    #AHIE_NOMEM,d0
  1863.     rts
  1864.  
  1865. ;in:
  1866. * a2    AudioCtrl
  1867. * a3    paula
  1868. * a5    paulaBase
  1869. * a6    ExecBase
  1870. init14bitS:
  1871.     PRINTF    2,"init14bitS()"
  1872.     move.l    #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
  1873.     lea    SoftInt_14bitS(pc),a0
  1874.     move.b    p_Flags(a3),d0
  1875.     btst    #PB_HIFI,d0
  1876.     beq    .nohifi1
  1877.     lea    SoftInt_14bitSH(pc),a0
  1878. .nohifi1
  1879.     tst.l    p_CalibrationTable(a3)
  1880.     beq.b    .nocalib
  1881.     lea    SoftInt_14CbitS(pc),a0
  1882.     move.b    p_Flags(a3),d0
  1883.     btst    #PB_HIFI,d0
  1884.     beq    .nohifi2
  1885.     lea    SoftInt_14CbitSH(pc),a0
  1886. .nohifi2
  1887. .nocalib
  1888.     move.l    a0,IS_CODE+p_PlaySoftInt(a3)
  1889.  
  1890.     move.l    p_MinBufferLength(a3),d0
  1891.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 16 bit samples
  1892.     addq.l    #3,d0
  1893.     and.b    #~3,d0                ;make it a multiple of 4
  1894.     move.l    d0,d2                ;d2 = channel size
  1895.  
  1896.     lsl.l    #3,d0                ;Double buffer + 2×8 bit + Stereo
  1897.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1898.     call    AllocVec
  1899.     move.l    d0,p_DMAbuffer(a3)
  1900.     beq    .nomem
  1901.  
  1902.     move.l    d0,p_AudPtr1A(a3)
  1903.     add.l    d2,d0
  1904.     move.l    d0,p_AudPtr2A(a3)
  1905.     add.l    d2,d0
  1906.     move.l    d0,p_AudPtr3A(a3)
  1907.     add.l    d2,d0
  1908.     move.l    d0,p_AudPtr4A(a3)
  1909.     add.l    d2,d0
  1910.     move.l    d0,p_AudPtr1B(a3)
  1911.     add.l    d2,d0
  1912.     move.l    d0,p_AudPtr2B(a3)
  1913.     add.l    d2,d0
  1914.     move.l    d0,p_AudPtr3B(a3)
  1915.     add.l    d2,d0
  1916.     move.l    d0,p_AudPtr4B(a3)
  1917.  
  1918. ;    move.w    #64,AUD0VOL(a4)
  1919. ;    move.w    #64,AUD1VOL(a4)
  1920. ;    move.w    #1,AUD2VOL(a4)
  1921. ;    move.w    #1,AUD3VOL(a4)
  1922.  
  1923.     moveq    #0,d0
  1924.     rts
  1925. .nomem
  1926.     moveq    #AHIE_NOMEM,d0
  1927.     rts
  1928.  
  1929. ****** [driver].audio/AHIsub_Update *****************************************
  1930. *
  1931. *   NAME
  1932. *       AHIsub_Update -- Update some variables
  1933. *
  1934. *   SYNOPSIS
  1935. *       AHIsub_Update( flags, audioctrl );
  1936. *                      D0     A2
  1937. *
  1938. *       void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
  1939. *
  1940. *   IMPLEMENTATION
  1941. *       All you have to do is to update some variables:
  1942. *       Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
  1943. *       ahiac_BuffSamples (and perhaps ahiac_PlayerFreq if you use it).
  1944. *       Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc and
  1945. *           ahiac_PlayerFreq.
  1946. *       Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc and ahiac_PlayerFreq.
  1947. *
  1948. *   INPUTS
  1949. *       flags - Currently no flags defined.
  1950. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1951. *
  1952. *   RESULT
  1953. *
  1954. *   NOTES
  1955. *       This call must be safe from interrupts.
  1956. *
  1957. *   SEE ALSO
  1958. *       AHIsub_Start()
  1959. *
  1960. *****************************************************************************
  1961. *
  1962. *
  1963. *
  1964.  
  1965. AHIsub_Update:
  1966.     pushm    d2-d7/a2-a6
  1967.  
  1968.     call    AHIsub_Disable        ;make sure we don't get an interrupt
  1969.                     ;while updating our local variables
  1970.     move.l    ahiac_DriverData(a2),a3
  1971.  
  1972.     move.l    ahiac_PlayerFunc(a2),a0
  1973.     move.l    a0,p_PlayerHook(a3)
  1974.     move.l    h_Entry(a0),p_PlayerEntry(a3)
  1975.  
  1976.     move.l    ahiac_BuffSamples(a2),d1
  1977.     and.b    #~3,d1            ;make it a multiple of 4
  1978.     move.l    d1,ahiac_BuffSamples(a2)
  1979.     move.l    d1,d0
  1980.     lsr.l    #2,d0
  1981.     subq.l    #1,d0
  1982.     move.l    d0,p_LoopTimes(a3)    ;See softints. (Unrolled)
  1983.  
  1984.     PRINTF    2,"LoopTimes: %ld", d0
  1985.  
  1986. ;    move.l    p_MinBufferLength(a3),d0
  1987. ;    divu.w    d1,d0
  1988. ;    ext.l    d0
  1989. ;    move.l    d0,p_RepeatTimes(a3)    ;that's really times-1 (dbf dx,label)
  1990.  
  1991. ;    PRINTF    2,"RepeatTimes: %ld", d0
  1992.  
  1993. ;    addq.l    #1,d0
  1994. ;    mulu.w    d1,d0
  1995. ;    lsr.l    #1,d0            ;length in words
  1996. ;    move.w    d0,p_AudLen(a3)
  1997.  
  1998. ;    PRINTF    2,"AudLen: %ld", d0
  1999.  
  2000.     move.l    ahiac_MixerFunc(a2),a0
  2001.     move.l    a0,p_MixHook(a3)
  2002.     move.l    h_Entry(a0),p_MixEntry(a3)
  2003.  
  2004.     call    AHIsub_Enable
  2005.     moveq    #0,d0
  2006.     popm    d2-d7/a2-a6
  2007.     rts
  2008.  
  2009.  
  2010. ****** [driver].audio/AHIsub_Stop *******************************************
  2011. *
  2012. *   NAME
  2013. *       AHIsub_Stop -- Stops playback.
  2014. *
  2015. *   SYNOPSIS
  2016. *       AHIsub_Stop( flags, audioctrl );
  2017. *                    D0     A2
  2018. *
  2019. *       void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
  2020. *
  2021. *   IMPLEMENTATION
  2022. *       Stop playback and/or recording, remove all resources allocated by
  2023. *       AHIsub_Start().
  2024. *
  2025. *   INPUTS
  2026. *       flags - See <libraries/ahi_sub.h>.
  2027. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  2028. *
  2029. *   NOTES
  2030. *       It must be safe to call this routine even if AHIsub_Start() was never
  2031. *       called, failed or called more than once.
  2032. *
  2033. *   SEE ALSO
  2034. *       AHIsub_Start()
  2035. *
  2036. *****************************************************************************
  2037. *
  2038. *
  2039.  
  2040. AHIsub_Stop:
  2041.     pushm    d2-d7/a2-a6
  2042.  
  2043.     lea    custom,a4
  2044.     move.l    a6,a5
  2045.     move.l    pb_SysLib(a5),a6
  2046.     move.l    ahiac_DriverData(a2),a3
  2047.  
  2048.     push    d0
  2049.     btst    #AHISB_PLAY,d0
  2050.     beq    .dontplay
  2051.  
  2052. **
  2053. *** AHISB_PLAY
  2054. **
  2055.     move.w    #DMAF_AUDIO,DMACON(a4)        ;disable audio DMA
  2056.  
  2057.     move.w    #INTF_AUD0,INTENA(a4)
  2058.     move.w    #INTF_AUD0,INTREQ(a4)        ;Clear any waiting interrupts
  2059.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  2060.     lea    p_PlayInt(a3),a1
  2061.     moveq    #INTB_AUD0,d0
  2062.     call    SetIntVector
  2063.  
  2064.     moveq    #0,d0
  2065.     move.w    d0,AUD0VOL(a4)
  2066.     move.w    d0,AUD1VOL(a4)
  2067.     move.w    d0,AUD2VOL(a4)
  2068.     move.w    d0,AUD3VOL(a4)
  2069.  
  2070.     move.l    p_DMAbuffer(a3),d0
  2071.     beq.b    .nodmamem
  2072.     move.l    d0,a1
  2073.     clr.l    p_DMAbuffer(a3)
  2074.     call    FreeVec
  2075. .nodmamem
  2076.     move.l    p_Mixbuffer(a3),d0
  2077.     beq.b    .nomixmem
  2078.     move.l    d0,a1
  2079.     clr.l    p_Mixbuffer(a3)
  2080.     call    FreeVec
  2081. .nomixmem
  2082.  
  2083. .dontplay
  2084.     pop    d0
  2085.     btst    #AHISB_RECORD,d0
  2086.     beq    .dontrecord
  2087.  
  2088. **
  2089. *** AHISB_RECORD
  2090. **
  2091.     btst    #PB_14BIT,p_Flags(a3)        ;Sanity check...
  2092.     bne    .dontrecord
  2093.  
  2094.     move.w    #INTF_AUD3,INTENA(a4)
  2095.     move.w    #INTF_AUD3,INTREQ(a4)        ;Clear any waiting interrupts
  2096.  
  2097.     move.l    #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
  2098.     lea    p_RecInt(a3),a1
  2099.     moveq    #INTB_AUD3,d0
  2100.     call    SetIntVector
  2101.  
  2102.     move.w    #0,AUD2VOL(a4)
  2103.     move.w    #0,AUD3VOL(a4)
  2104.  
  2105.     move.l    p_RecBuffer1(a3),d0
  2106.     beq.b    .norecmem1
  2107.     move.l    d0,a1
  2108.     clr.l    p_RecBuffer1(a3)
  2109.     call    FreeVec
  2110. .norecmem1
  2111.     move.l    p_RecBuffer2(a3),d0
  2112.     beq.b    .norecmem2
  2113.     move.l    d0,a1
  2114.     clr.l    p_RecBuffer2(a3)
  2115.     call    FreeVec
  2116. .norecmem2
  2117. .dontrecord
  2118. .return
  2119.     moveq    #0,d0
  2120.     popm    d2-d7/a2-a6
  2121.     rts
  2122.  
  2123. ****** [driver].audio/AHIsub_#? *********************************************
  2124. *
  2125. *   NAME
  2126. *       AHIsub_SetEffect -- Set effect.
  2127. *       AHIsub_SetFreq -- Set frequency.
  2128. *       AHIsub_SetSound -- Set sound.
  2129. *       AHIsub_SetVol -- Set volume and stereo panning.
  2130. *       AHIsub_LoadSound -- Prepare a sound for playback.
  2131. *       AHIsub_UnloadSound -- Discard a sound.
  2132. *
  2133. *   SYNOPSIS
  2134. *       See functions in 'ahi.device'.
  2135. *
  2136. *   IMPLEMENTATION
  2137. *       If AHIsub_AllocAudio() did not return with bit AHISB_MIXING set,
  2138. *       all user calls to these function will be routed to the driver.
  2139. *
  2140. *       If AHIsub_AllocAudio() did return with bit AHISB_MIXING set, the
  2141. *       calls will first be routed to the driver, and only handled by
  2142. *       'ahi.device' if the driver returned AHIS_UNKNOWN. This way it is
  2143. *       possible to add effects that the sound card handles on its own, like
  2144. *       filter and echo effects.
  2145. *
  2146. *       For what each function does, see the autodocs for 'ahi.device'.
  2147. *
  2148. *   INPUTS
  2149. *       See functions in 'ahi.device'.
  2150. *
  2151. *   NOTES
  2152. *       See functions in 'ahi.device'.
  2153. *
  2154. *   SEE ALSO
  2155. *       ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
  2156. *       ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
  2157. *       ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
  2158. *       
  2159. *
  2160. *****************************************************************************
  2161. *
  2162. *
  2163.  
  2164. AHIsub_SetVol:
  2165. AHIsub_SetFreq:
  2166. AHIsub_SetSound:
  2167. AHIsub_SetEffect:
  2168. AHIsub_LoadSound:
  2169. AHIsub_UnloadSound:
  2170.     moveq    #AHIS_UNKNOWN,d0
  2171.     rts
  2172.  
  2173. ****** [driver].audio/AHIsub_GetAttr ****************************************
  2174. *
  2175. *   NAME
  2176. *       AHIsub_GetAttr -- Returns information about audio modes or driver
  2177. *
  2178. *   SYNOPSIS
  2179. *       AHIsub_GetAttr( attribute, argument, default, taglist, audioctrl );
  2180. *       D0              D0         D1        D2       A1       A2
  2181. *
  2182. *       LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
  2183. *                            struct AHIAudioCtrlDrv * );
  2184. *
  2185. *   IMPLEMENTATION
  2186. *       Return the attribute based on a tag list and an AHIAudioCtrlDrv
  2187. *       structure, which are the same that will be passed to
  2188. *       AHIsub_AllocAudio() by 'ahi.device'. If the attribute is
  2189. *       unknown to you, return the default.
  2190. *
  2191. *   INPUTS
  2192. *       attribute - Is really a Tag and can be one of the following:
  2193. *           AHIDB_Bits - Return how many output bits the tag list will
  2194. *               result in.
  2195. *           AHIDB_MaxChannels - Return the resulting number of channels.
  2196. *           AHIDB_Frequencies - Return how many mixing/sampling frequencies
  2197. *               you support
  2198. *           AHIDB_Frequency - Return the argument:th frequency
  2199. *               Example: You support 3 frequencies 32, 44.1 and 48 kHz.
  2200. *                   If argument is 1, return 44100.
  2201. *           AHIDB_Index - Return the index which gives the frequency closest
  2202. *               to argument.
  2203. *               Example: You support 3 frequencies 32, 44.1 and 48 kHz.
  2204. *                   If argument is 40000, return 1 (=> 44100).
  2205. *           AHIDB_Author - Return pointer to name of driver author:
  2206. *               "Martin 'Leviticus' Blom"
  2207. *           AHIDB_Copyright - Return pointer to copyright notice, including
  2208. *               the '©' character: "© 1996 Martin Blom" or "Public Domain"
  2209. *           AHIDB_Version - Return pointer version string, normal Amiga
  2210. *               format: "paula 1.5 (18.2.96)\r\n"
  2211. *           AHIDB_Annotation - Return pointer to an annotation string, which
  2212. *               can be several lines.
  2213. *           AHIDB_Record - Are you a sampler, too? Return TRUE or FALSE.
  2214. *           AHIDB_FullDuplex - Return TRUE or FALSE.
  2215. *           AHIDB_Realtime - Return TRUE or FALSE.
  2216. *           AHIDB_MaxPlaySamples - Normally, return the default. See
  2217. *               AHIsub_AllocAudio(), section 2.
  2218. *           AHIDB_MaxRecordSamples - Return the size of the buffer you fill
  2219. *               when recording.
  2220. *
  2221. *           The following are associated with AHIsub_HardwareControl() and are
  2222. *           new for V2.
  2223. *           AHIDB_MinMonitorVolume
  2224. *           AHIDB_MaxMonitorVolume - Return the lower/upper limit for
  2225. *               AHIC_MonitorVolume. If unsupported but always 1.0, return
  2226. *               1.0 for both.
  2227. *           AHIDB_MinInputGain
  2228. *           AHIDB_MaxInputGain - Return the lower/upper limit for
  2229. *               AHIC_InputGain. If unsupported but always 1.0, return 1.0 for
  2230. *               both.
  2231. *           AHIDB_MinOutputVolume
  2232. *           AHIDB_MaxOutputVolume - Return the lower/upper limit for
  2233. *               AHIC_OutputVolume.
  2234. *           AHIDB_Inputs - Return how many inputs you have.
  2235. *           AHIDB_Input - Return a short string describing the argument:th
  2236. *               input. Number 0 should be the default one. Example strings
  2237. *               can be "Line 1", "Mic", "Optical" or whatever.
  2238. *           AHIDB_Outputs - Return how many outputs you have.
  2239. *           AHIDB_Output - Return a short string describing the argument:th
  2240. *               output. Number 0 should be the default one. Example strings
  2241. *               can be "Line 1", "Headphone", "Optical" or whatever.
  2242. *       argument - extra info for some attributes.
  2243. *       default - What you should return for unknown attributes.
  2244. *       taglist - Pointer to a tag list that eventually will be fed to
  2245. *           AHIsub_AllocAudio(), or NULL.
  2246. *       audioctrl - Pointer to an AHIAudioCtrlDrv structure that eventually
  2247. *           will be fed to AHIsub_AllocAudio(), or NULL.
  2248. *
  2249. *   NOTES
  2250. *
  2251. *   SEE ALSO
  2252. *       AHIsub_AllocAudio(), AHIsub_HardwareControl(),
  2253. *       ahi.device/AHI_GetAudioAttrsA()
  2254. *
  2255. *****************************************************************************
  2256. *
  2257. *
  2258.  
  2259. AHIsub_GetAttr:
  2260.     pushm    d2-d7/a2-a6
  2261.     move.l    a6,a5
  2262.     move.l    pb_UtilLib(a5),a6
  2263.  
  2264.  
  2265.     pushm    d0-d1
  2266.     moveq    #FALSE,d3
  2267.     move.l    a1,a0
  2268.     move.l    a1,d0
  2269.     beq    .notaglist
  2270.     move.l    #AHIDB_Paula14Bit,d0
  2271.     move.l    d3,d1
  2272.     call    GetTagData
  2273.     move.l    d0,d3
  2274. .notaglist
  2275.     popm    d0-d1
  2276.  
  2277.     and.l    #~(AHI_TagBaseR),d0
  2278.     cmp.l    #AHIDB_Data & ~(AHI_TagBaseR),d0
  2279.     bhi    .default
  2280.     sub.w    #100,d0
  2281.     lsl.w    #1,d0
  2282.     move.w    .jt(pc,d0.w),d0
  2283.     beq    .default
  2284.     jsr    .jt(pc,d0.w)
  2285.  
  2286. .exit
  2287.     popm    d2-d7/a2-a6
  2288.     rts
  2289.  
  2290. .default
  2291.     move.l    d2,d0
  2292.     bra    .exit
  2293.  
  2294. .jt
  2295.     dc.w    0                ; AHIDB_AudioID
  2296.     dc.w    0                ; AHIDB_Driver
  2297.     dc.w    0                ; AHIDB_Flags
  2298.     dc.w    0                ; AHIDB_Volume
  2299.     dc.w    0                ; AHIDB_Panning
  2300.     dc.w    0                ; AHIDB_Stereo
  2301.     dc.w    0                ; AHIDB_HiFi
  2302.     dc.w    0                ; AHIDB_PingPong
  2303.     dc.w    0                ; AHIDB_MultTable
  2304.     dc.w    0                ; AHIDB_Name
  2305.     dc.w    ga_Bits-.jt            ; AHIDB_Bits
  2306.     dc.w    0                ; AHIDB_MaxChannels
  2307.     dc.w    0                ; AHIDB_MinMixFreq
  2308.     dc.w    0                ; AHIDB_MaxMixFreq
  2309.     dc.w    ga_Record-.jt            ; AHIDB_Record
  2310.     dc.w    ga_Frequencies-.jt        ; AHIDB_Frequencies
  2311.     dc.w    0                ; AHIDB_FrequencyArg
  2312.     dc.w    ga_Frequency-.jt        ; AHIDB_Frequency
  2313.     dc.w    ga_Author-.jt            ; AHIDB_Author
  2314.     dc.w    ga_Copyright-.jt        ; AHIDB_Copyright
  2315.     dc.w    ga_Version-.jt            ; AHIDB_Version
  2316.     dc.w    ga_Annotation-.jt        ; AHIDB_Annotation
  2317.     dc.w    0                ; AHIDB_BufferLen
  2318.     dc.w    0                ; AHIDB_IndexArg
  2319.     dc.w    ga_Index-.jt            ; AHIDB_Index
  2320.     dc.w    ga_Realtime-.jt            ; AHIDB_Realtime
  2321.     dc.w    0                ; AHIDB_MaxPlaySamples
  2322.     dc.w    ga_MaxRecordSamples-.jt        ; AHIDB_MaxRecordSample
  2323.     dc.w    0                ; 
  2324.     dc.w    ga_FullDuplex-.jt        ; AHIDB_FullDuplex
  2325.     dc.w    ga_MinMonitorVolume-.jt        ; AHIDB_MinMonitorVolum
  2326.     dc.w    ga_MaxMonitorVolume-.jt        ; AHIDB_MaxMonitorVolum
  2327.     dc.w    ga_MinInputGain-.jt        ; AHIDB_MinInputGain
  2328.     dc.w    ga_MaxInputGain-.jt        ; AHIDB_MaxInputGain
  2329.     dc.w    ga_MinOutputVolume-.jt        ; AHIDB_MinOutputVolume
  2330.     dc.w    ga_MaxOutputVolume-.jt        ; AHIDB_MaxOutputVolume
  2331.     dc.w    ga_Inputs-.jt            ; AHIDB_Inputs
  2332.     dc.w    0                ; AHIDB_InputArg
  2333.     dc.w    ga_Input-.jt            ; AHIDB_Input
  2334.     dc.w    ga_Outputs-.jt            ; AHIDB_Outputs
  2335.     dc.w    0                ; AHIDB_OutputArg
  2336.     dc.w    ga_Output-.jt            ; AHIDB_Output
  2337.     dc.w    0                ; AHIDB_Data
  2338.  
  2339. ga_Bits:
  2340.     moveq    #14,d0
  2341.     tst.l    d3
  2342.     bne    .exit
  2343.     moveq    #8,d0
  2344. .exit
  2345.     rts
  2346.  
  2347. ga_Record:
  2348.     moveq    #FALSE,d0
  2349.     tst.l    d3
  2350.     bne    .exit
  2351.     moveq    #TRUE,d0
  2352. .exit
  2353.     rts
  2354.  
  2355. ga_Frequencies:
  2356.     bsr    checkvideo
  2357.     tst.l    d0
  2358.     beq    .1
  2359.     moveq    #FREQUENCIES,d0
  2360.     rts
  2361. .1
  2362.     moveq    #FREQUENCIES_OCS,d0
  2363.     rts
  2364.  
  2365. ga_Frequency:
  2366.     lsl.w    #2,d1
  2367.     lea    freqlist(pc),a0
  2368. ;    move.l    (a0,d1.w),d1
  2369. ;    bsr    calcperiod
  2370.     move.l    (a0,d1.w),d0
  2371.     rts
  2372.  
  2373. ga_Author:
  2374.     lea    .author(pc),a0
  2375.     move.l    a0,d0
  2376.     rts
  2377. .author        dc.b    "Martin 'Leviticus' Blom",0
  2378.     even
  2379.  
  2380. ga_Copyright:
  2381.     lea    .copyright(pc),a0
  2382.     move.l    a0,d0
  2383.     rts
  2384. .copyright    dc.b    "Public Domain",0
  2385.     even
  2386.  
  2387. ga_Version:
  2388.     lea    IDString(pc),a0
  2389.     move.l    a0,d0
  2390.     rts
  2391.  
  2392. ga_Annotation:
  2393.     lea    .anno(pc),a0
  2394.     move.l    a0,d0
  2395.     rts
  2396. .anno        dc.b    "14 bit routines by Christian Buchner.",0
  2397.     even
  2398.  
  2399. ga_Index:
  2400.     move.l    d1,d0
  2401.     bsr    findfreq
  2402.     move.l    d1,d0
  2403.     rts
  2404.  
  2405.  
  2406. ga_Realtime:
  2407.     moveq    #TRUE,d0
  2408.     rts
  2409.  
  2410. ga_MaxRecordSamples:
  2411.     move.l    #RECORDSAMPLES,d0
  2412.     rts
  2413.  
  2414. ga_FullDuplex:
  2415.     moveq    #FALSE,d0
  2416.     tst.l    d3
  2417.     bne    .exit
  2418.     moveq    #TRUE,d0
  2419. .exit
  2420.     rts
  2421.  
  2422.  
  2423. ga_MinMonitorVolume:
  2424.     moveq    #0,d0
  2425.     rts
  2426.  
  2427. ga_MaxMonitorVolume:
  2428.     moveq    #0,d0
  2429.     tst.l    d3
  2430.     bne    .exit
  2431.     move.l    #$10000,d0
  2432. .exit
  2433.     rts
  2434.  
  2435. ga_MinInputGain:
  2436.     move.l    #$10000,d0
  2437.     rts
  2438.  
  2439. ga_MaxInputGain:
  2440.     move.l    #$10000,d0
  2441.     rts
  2442.  
  2443. ga_MinOutputVolume:
  2444.     move.l    #$10000,d0
  2445.     tst.l    d3
  2446.     bne    .exit
  2447.     moveq    #0,d0
  2448. .exit
  2449.     rts
  2450.  
  2451. ga_MaxOutputVolume:
  2452.     move.l    #$10000,d0
  2453.     rts
  2454.  
  2455.  
  2456. ga_Inputs:
  2457.     moveq    #0,d0
  2458.     tst.l    d3
  2459.     bne    .exit
  2460.     moveq    #3,d0
  2461. .exit
  2462.     rts
  2463.  
  2464. ga_Input:
  2465.     lsl.l    #2,d1
  2466.     move.l    .inputs(pc,d1.w),d0
  2467.     rts
  2468. .inputs        dc.l    .input0
  2469.         dc.l    .input1
  2470.         dc.l    .input2
  2471.  
  2472. .input0        dc.b    "Parallel port sampler",0
  2473. .input1        dc.b    "Aura sampler",0
  2474. .input2        dc.b    "Clarity sampler",0
  2475.     even
  2476.  
  2477. ga_Outputs:
  2478.     moveq    #1,d0
  2479.     rts
  2480.  
  2481. ga_Output:
  2482.     lea    .output(pc),a0
  2483.     move.l    a0,d0
  2484.     rts
  2485. .output        dc.b    "Line",0
  2486.     even
  2487.  
  2488.  
  2489. ****** [driver].audio/AHIsub_HardwareControl ********************************
  2490. *
  2491. *   NAME
  2492. *       AHIsub_HardwareControl -- Modify sound card settings
  2493. *
  2494. *   SYNOPSIS
  2495. *       AHIsub_HardwareControl( attribute,  argument, audioctrl );
  2496. *       D0                      D0          D1        A2
  2497. *
  2498. *       LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
  2499. *
  2500. *   IMPLEMENTATION
  2501. *       Set or return the state of a particular hardware component. AHI uses
  2502. *       AHIsub_GetAttr() to supply the user with limits and what tags are
  2503. *       available.
  2504. *
  2505. *   INPUTS
  2506. *       attribute - Is really a Tag and can be one of the following:
  2507. *           AHIC_MonitorVolume - Set the input monitor volume to argument.
  2508. *           AHIC_MonitorVolume_Query - Return the current input monitor
  2509. *               volume (argument is ignored).
  2510. *
  2511. *           AHIC_InputGain - Set the input gain to argument. (V2)
  2512. *           AHIC_InputGain_Query (V2)
  2513. *
  2514. *           AHIC_OutputVolume - Set the output volume to argument. (V2)
  2515. *           AHIC_OutputVolume_Query (V2)
  2516. *
  2517. *           AHIC_Input - Use the argument:th input source (default is 0). (V2)
  2518. *           AHIC_Input_Query (V2)
  2519. *
  2520. *           AHIC_Output - Use the argument:th output destination (default
  2521. *               is 0). (V2)
  2522. *           AHIC_Output_Query (V2)
  2523. *
  2524. *       argument - What value attribute should be set to.
  2525. *       audioctrl - Pointer to an AHIAudioCtrlDrv structure.
  2526. *
  2527. *   RESULT
  2528. *       Return the state of selected attribute. If you were asked to set
  2529. *       something, return TRUE. If attribute is unknown to you or unsupported,
  2530. *       return FALSE.
  2531. *
  2532. *   NOTES
  2533. *       This call must be safe from interrupts.
  2534. *
  2535. *   SEE ALSO
  2536. *       ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
  2537. *
  2538. *****************************************************************************
  2539. *
  2540. *
  2541.  
  2542. AHIsub_HardwareControl:
  2543.     cmp.l    #AHIC_MonitorVolume,d0
  2544.     bne.b    .dontsetmonvol
  2545.     move.l    ahiac_DriverData(a2),a1
  2546.     lsr.l    #8,d1
  2547.     lsr.l    #2,d1
  2548.     move.w    d1,p_MonitorVolume(a1)
  2549.     bra.b    .exit
  2550. .dontsetmonvol
  2551.     cmp.l    #AHIC_MonitorVolume_Query,d0
  2552.     bne.b    .dontgetmonvol
  2553.     move.l    ahiac_DriverData(a2),a1
  2554.     moveq    #0,d0
  2555.     move.w    p_MonitorVolume(a1),d0
  2556.     lsl.l    #8,d0
  2557.     lsl.l    #2,d0
  2558.     bra.b    .quit
  2559. .dontgetmonvol
  2560.     cmp.l    #AHIC_OutputVolume,d0
  2561.     bne.b    .dontsetoutvol
  2562.     move.l    ahiac_DriverData(a2),a1
  2563.     lsr.l    #8,d1
  2564.     lsr.l    #2,d1
  2565.     move.w    d1,p_OutputVolume(a1)
  2566.     bra.b    .exit
  2567. .dontsetoutvol
  2568.     cmp.l    #AHIC_OutputVolume_Query,d0
  2569.     bne.b    .dontgetoutvol
  2570.     move.l    ahiac_DriverData(a2),a1
  2571.     moveq    #0,d0
  2572.     move.w    p_OutputVolume(a1),d0
  2573.     lsl.l    #8,d0
  2574.     lsl.l    #2,d0
  2575.     bra.b    .quit
  2576. .dontgetoutvol
  2577.     cmp.l    #AHIC_Input,d0
  2578.     bne.b    .dontsetinput
  2579.     move.l    ahiac_DriverData(a2),a1
  2580.     move.w    d1,p_Input(a1)
  2581.     bra.b    .exit
  2582. .dontsetinput
  2583.     cmp.l    #AHIC_Input_Query,d0
  2584.     bne.b    .dontgetinput
  2585.     move.l    ahiac_DriverData(a2),a1
  2586.     moveq    #0,d0
  2587.     move.w    p_Input(a1),d0
  2588.     bra.b    .quit
  2589. .dontgetinput
  2590.     moveq    #FALSE,d0
  2591. .quit
  2592.     rts
  2593. .exit
  2594.     moveq    #TRUE,d0
  2595.     rts
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603. *******************************************************************************
  2604. *******************************************************************************
  2605.  
  2606. Interrupt_Dummy:
  2607.     move.w    #INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3,INTREQ(a0)
  2608. SoftInt_Dummy:
  2609.     rts
  2610.  
  2611. *******************************************************************************
  2612. *******************************************************************************
  2613.  
  2614. ;in:
  2615. * d0    scratch
  2616. * d1    INTENAR & INTREQR
  2617. * a0    custom
  2618. * a1    &(paula->p_RecIntData)
  2619. * a5    &RecordInterrupt
  2620. * a6    ExecBase
  2621. RecordInterrupt:
  2622.  
  2623. * This function will be executed up to 28000 times per second - that's once per
  2624. * rasterline! It has to be as fast as possible.
  2625.  
  2626.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  2627.     moveq    #0,d0
  2628.     move.b    _ciaa+ciaprb,d0            ;read parallel port
  2629.  IFGE    __CPU-68020
  2630.     move.l    convtable(pc,d0.w*4),d0        ;1 unsigned byte -> 2 signed words
  2631.  ELSE
  2632.     add.w    d0,d0
  2633.     add.w    d0,d0
  2634.     move.l    convtable(pc,d0.w),d0
  2635.  ENDC
  2636.     move.w    d0,AUD2DAT(a0)            ;left
  2637.     move.w    d0,AUD3DAT(a0)            ;right
  2638.  
  2639.     move.l    (a1),a5                ;p_RecFillPtr
  2640.     move.l    d0,(a5)+            ;store sample in buffer
  2641.     move.l    a5,(a1)+            ;update pointer
  2642.     subq.w    #1,(a1)                ;p_ReqFillCount
  2643.     beq    ri_Filled            ;branch if buffer filled
  2644.     rts
  2645.  
  2646. convtable
  2647. CNT    SET    0
  2648.     REPT    256
  2649.     dc.b    CNT-128,CNT-128,CNT-128,CNT-128
  2650. CNT    SET    CNT+1
  2651.     ENDR
  2652.  
  2653. ;in:
  2654. * d0    scratch
  2655. * d1    INTENAR & INTREQR
  2656. * a0    custom
  2657. * a1    &(paula->p_RecIntData)
  2658. * a5    &RecordInterrupt
  2659. * a6    ExecBase
  2660. RecordInterruptClarity:
  2661.  
  2662. * This function will be executed up to 28000 times per second - that's once per
  2663. * rasterline! It has to be as fast as possible.
  2664.  
  2665.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  2666.  
  2667.     lea    _ciab+ciatahi,a5
  2668.  
  2669.     move.b    _ciaa+ciaprb,d0            ;left lsb
  2670.     ror.l    #8,d0                ;d0: L0xxxxxx
  2671.     tst.b    (a5)                ;3x700 kHz wait states
  2672.     tst.b    (a5)
  2673.     tst.b    (a5)
  2674.  
  2675.     move.b    _ciaa+ciaprb,d0            ;left msb
  2676.     ror.l    #8,d0                ;d0: L1L0xxxx
  2677.     tst.b    (a5)                ;3x700 kHz wait states
  2678.     tst.b    (a5)
  2679.     tst.b    (a5)
  2680.  
  2681.     move.b    _ciaa+ciaprb,d0            ;right lsb
  2682.     lsl.w    #8,d0                ;d0: L1L0R0xx
  2683.     tst.b    (a5)                ;3x700 kHz wait states
  2684.     tst.b    (a5)
  2685.     tst.b    (a5)
  2686.  
  2687.     move.b    _ciaa+ciaprb,d0            ;right msb
  2688.     ror.w    #8,d0                ;d0: L1L0R1R0
  2689.  
  2690.     move.l    (a1),a5                ;p_RecFillPtr
  2691.     move.l    d0,(a5)+            ;store sample in buffer
  2692.     move.l    a5,(a1)+            ;update pointer
  2693.  
  2694.     move.w    d0,d1
  2695.     lsr.w    #8,d0
  2696.     move.b    d0,d1
  2697.  
  2698.     move.w    d1,AUD2DAT(a0)            ;right
  2699.     move.w    d1,AUD3DAT(a0)            ;left
  2700.  
  2701.     subq.w    #1,(a1)                ;p_ReqFillCount
  2702.     beq    ri_Filled            ;branch if buffer filled
  2703.     rts
  2704.  
  2705. ;in:
  2706. * d0    scratch
  2707. * d1    INTENAR & INTREQR
  2708. * a0    custom
  2709. * a1    &(paula->p_RecIntDataAura)
  2710. * a5    &RecordInterrupt
  2711. * a6    ExecBase
  2712. RecordInterruptAura:
  2713.  
  2714. * This function will be executed up to 28000 times per second - that's once per
  2715. * rasterline! It has to be as fast as possible.
  2716.  
  2717.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  2718.     move.l    (a1)+,a5
  2719.     move.l    (a5),d0                ;read aura sampler
  2720.     eor.l    #$80008000,d0
  2721.     move.l    (a1),a5                ;p_RecFillPtr
  2722.     move.l    d0,(a5)+            ;store sample in buffer
  2723.     move.l    a5,(a1)+            ;update pointer
  2724.  
  2725.     move.w    d0,d1
  2726.     lsr.w    #8,d0
  2727.     move.b    d0,d1
  2728.  
  2729.     move.w    d1,AUD2DAT(a0)            ;left
  2730.     move.w    d1,AUD3DAT(a0)            ;right
  2731.  
  2732.     subq.w    #1,(a1)                ;p_ReqFillCount
  2733.     beq    ri_Filled            ;branch if buffer filled
  2734.     rts
  2735.  
  2736. *******************************************************************************
  2737.  
  2738. ri_Filled:
  2739.  
  2740. * This part is only executed every RECORDSAMPLES:th time... No need to hurry.
  2741.  
  2742.     move.l    8(a1),d0            ;p_RecBuffer2->
  2743.     move.l    4(a1),8(a1)            ;p_RecBuffer1->p_RecBuffer2
  2744.     move.l    d0,4(a1)            ;            ->p_RecBuffer1
  2745.     move.l    d0,-4(a1)            ;p_RecFillPtr
  2746.     move.w    #RECORDSAMPLES,(a1)        ;p_ReqFillCount
  2747.     move.l    12(a1),a1            ;p_RecSoftIntPtr
  2748.     jmp    _LVOCause(a6)
  2749.  
  2750.  
  2751. ;in:
  2752. * d0    scratch
  2753. * d1    scratch
  2754. * a0    scratch
  2755. * a1    struct paula *
  2756. * a5    scratch
  2757. RecordSoftInt:
  2758.  
  2759. * This function is not executed many times per second and is therefore not
  2760. * fully optimized... ;)
  2761.     push    a2
  2762.     move.w    p_MonitorVolume(a1),d0
  2763.     move.w    d0,custom+AUD2VOL
  2764.     move.w    d0,custom+AUD3VOL
  2765.     move.l    p_RecBuffer2(a1),p_rmBuffer(a1)
  2766.     move.l    p_AudioCtrl(a1),a2
  2767.     lea    p_RecordMessage(a1),a1
  2768.     move.l    ahiac_SamplerFunc(a2),a0
  2769.     move.l    h_Entry(a0),a5
  2770.     jsr    (a5)
  2771.     pop    a2
  2772.     rts
  2773.  
  2774. *******************************************************************************
  2775. *******************************************************************************
  2776.  
  2777. ;in:
  2778. * d0    scratch
  2779. * d1    INTENAR & INTREQR
  2780. * a0    custom
  2781. * a1    struct paula *
  2782. * a5    &AudioInterrupt
  2783. * a6    ExecBase
  2784.  
  2785. AudioInterrupt2:                ;Two hardware channels used
  2786. ;    move.l    p_AudLenPer(a1),d0
  2787. ;    move.l    d0,AUD0LEN(a0)
  2788. ;    move.l    d0,AUD1LEN(a0)
  2789.     move.w    p_AudPer(a1),d0
  2790.     move.w    d0,AUD0PER(a0)
  2791.     move.w    d0,AUD1PER(a0)
  2792.     move.w    p_OutputVolume(a1),AUD0VOL(a0)
  2793.     move.w    p_OutputVolume(a1),AUD1VOL(a0)
  2794.  
  2795.     move.l    p_DoubleBufferOffset(a1),d0
  2796.     eor.w    #4*4,d0
  2797.     move.l    d0,p_DoubleBufferOffset(a1)
  2798.  
  2799.     lea    p_AudPtrs(a1,d0.l),a5
  2800.     tst.w    p_SwapChannels(a1)
  2801.     bne    .swap
  2802.     move.l    (a5)+,AUD0LC(a0)
  2803.     move.l    (a5)+,AUD1LC(a0)
  2804.     bra    .1
  2805. .swap
  2806.     move.l    (a5)+,AUD1LC(a0)
  2807.     move.l    (a5)+,AUD0LC(a0)
  2808. .1
  2809.     lea    p_PlaySoftInt(a1),a1
  2810.     move.w    #INTF_AUD0,INTREQ(a0)        ;Clear the interrupt 
  2811.     jmp    _LVOCause(a6)            ;start PlaySoftInt
  2812.  
  2813.  
  2814. AudioInterrupt4:                ;Four hardware channels used
  2815. ;    move.l    p_AudLenPer(a1),d0
  2816. ;    move.l    d0,AUD0LEN(a0)
  2817. ;    move.l    d0,AUD1LEN(a0)
  2818. ;    move.l    d0,AUD2LEN(a0)
  2819. ;    move.l    d0,AUD3LEN(a0)
  2820.     move.w    p_AudPer(a1),d0
  2821.     move.w    d0,AUD0PER(a0)
  2822.     move.w    d0,AUD1PER(a0)
  2823.     move.w    d0,AUD2PER(a0)
  2824.     move.w    d0,AUD3PER(a0)
  2825.     move.w    #64,AUD0VOL(a0)
  2826.     move.w    #64,AUD1VOL(a0)
  2827.     move.w    #1,AUD2VOL(a0)
  2828.     move.w    #1,AUD3VOL(a0)
  2829.  
  2830.     move.l    p_DoubleBufferOffset(a1),d0
  2831.     eor.w    #4*4,d0
  2832.     move.l    d0,p_DoubleBufferOffset(a1)
  2833.  
  2834.     lea    p_AudPtrs(a1,d0.l),a5
  2835.     tst.w    p_SwapChannels(a1)
  2836.     bne    .swap
  2837.     move.l    (a5)+,AUD0LC(a0)
  2838.     move.l    (a5)+,AUD1LC(a0)
  2839.     move.l    (a5)+,AUD2LC(a0)
  2840.     move.l    (a5)+,AUD3LC(a0)
  2841.     bra    .1
  2842. .swap
  2843.     move.l    (a5)+,AUD1LC(a0)
  2844.     move.l    (a5)+,AUD0LC(a0)
  2845.     move.l    (a5)+,AUD3LC(a0)
  2846.     move.l    (a5)+,AUD2LC(a0)
  2847. .1
  2848.     lea    p_PlaySoftInt(a1),a1
  2849.     move.w    #INTF_AUD0,INTREQ(a0)        ;Clear the interrupt 
  2850.     jmp    _LVOCause(a6)            ;start PlaySoftInt
  2851.  
  2852.  
  2853. *******************************************************************************
  2854.  
  2855. ;in:
  2856. * d0    scratch
  2857. * d1    scratch
  2858. * a0    scratch
  2859. * a1    struct paula *
  2860. * a5    scratch
  2861.  
  2862. CONVERT_PRE    MACRO
  2863.     pushm    std
  2864.     move.l    a1,a6
  2865.     move.l    p_AudioCtrl(a6),a2
  2866.     move.l    ahiac_PreTimer(a2),a0
  2867.     jsr    (a0)
  2868.     move.l    d0,d7
  2869.  
  2870.     move.l    p_DoubleBufferOffset(a6),d0
  2871.     lea    p_AudPtrs(a6,d0.l),a0
  2872.     movem.l    (a0)+,d2/d3/d4/d5        ;get all 4 buffer pointers
  2873.  
  2874.     moveq    #0,d6
  2875. .repeat
  2876.     movem.l    p_PlayerHookRegs(a6),a0/a1/a3
  2877.     jsr    (a3)                ;call Player Hook
  2878.     tst.l    d7
  2879.     bne    .skip
  2880.     movem.l    p_MixHookRegs(a6),a0/a1/a3
  2881.     jsr    (a3)                ;call Mixer Hook
  2882.     move.l    p_LoopTimes(a6),d0
  2883.     ENDM
  2884.  
  2885. ;
  2886. ; Conversion code here!
  2887. ;
  2888. ; d0    counter
  2889. ; d1    scratch
  2890. ; d2-d5    buffer pointers
  2891. ; d6    (sample counter/4)
  2892. ; d7    (pretimer flag)
  2893. ; a0    scratch
  2894. ; a1    source buffer
  2895. ; a2    AudioCtrl
  2896. ; a3-a5    scratch
  2897. ; a6    struct paula *
  2898. ;
  2899. ; Conversion code here!
  2900. ;
  2901.  
  2902. CONVERT_POST    MACRO
  2903. .skip
  2904.     add.l    ahiac_BuffSamples(a2),d6
  2905.     cmp.l    p_MinBufferLength(a6),d6
  2906.     blo    .repeat
  2907.     move.l    ahiac_PostTimer(a2),a0
  2908.     jsr    (a0)
  2909.     move.l    d6,d0
  2910.     lea    custom,a0
  2911.     popm    std
  2912.     ENDM
  2913.  
  2914. ; Exit code here
  2915. ; d0    Samples in buffer
  2916. ; a0    custom
  2917.  
  2918. *******************************************************************************
  2919.  
  2920. SoftInt_8bitM:
  2921.  
  2922.     CONVERT_PRE
  2923.  
  2924.     move.l    d2,a0                ;get buffer ptr
  2925. .loop
  2926.     move.b    (a1),d1
  2927.     lsl.l    #8,d1
  2928.     move.b    2(a1),d1
  2929.     lsl.l    #8,d1
  2930.     move.b    4(a1),d1
  2931.     lsl.l    #8,d1
  2932.     move.b    6(a1),d1
  2933.     move.l    d1,(a0)+
  2934.     addq.w    #8,a1
  2935.     dbf    d0,.loop
  2936.     move.l    a0,d2                ;save buffer ptr
  2937.  
  2938.     CONVERT_POST
  2939.  
  2940.     lsr.l    #1,d0
  2941.     move.w    d0,AUD0LEN(a0)
  2942.     move.w    d0,AUD1LEN(a0)
  2943.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  2944.     rts
  2945.  
  2946. *******************************************************************************
  2947.  
  2948. SoftInt_8bitMH:
  2949.     CONVERT_PRE
  2950.  
  2951.     move.l    d2,a0                ;get buffer ptr
  2952. .loop
  2953.     move.b    (a1),d1
  2954.     lsl.l    #8,d1
  2955.     move.b    4(a1),d1
  2956.     lsl.l    #8,d1
  2957.     move.b    8(a1),d1
  2958.     lsl.l    #8,d1
  2959.     move.b    12(a1),d1
  2960.     move.l    d1,(a0)+
  2961.     add.w    #16,a1
  2962.     dbf    d0,.loop
  2963.     move.l    a0,d2                ;save buffer ptr
  2964.  
  2965.     CONVERT_POST
  2966.  
  2967.     lsr.l    #1,d0
  2968.     move.w    d0,AUD0LEN(a0)
  2969.     move.w    d0,AUD1LEN(a0)
  2970.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  2971.     rts
  2972.  
  2973. *******************************************************************************
  2974.  
  2975. SoftInt_8bitS:
  2976.     CONVERT_PRE
  2977.  
  2978.     move.l    d2,a0                ;get buffer ptr
  2979.     move.l    d3,a3                ;get buffer ptr
  2980. .loop
  2981.  
  2982. ; Left
  2983.     move.b    (a1),d1
  2984.     lsl.l    #8,d1
  2985.     move.b    4(a1),d1
  2986.     lsl.l    #8,d1
  2987.     move.b    8(a1),d1
  2988.     lsl.l    #8,d1
  2989.     move.b    12(a1),d1
  2990.     move.l    d1,(a3)+
  2991.  
  2992. ; Right
  2993.     move.b    2(a1),d1
  2994.     lsl.l    #8,d1
  2995.     move.b    6(a1),d1
  2996.     lsl.l    #8,d1
  2997.     move.b    10(a1),d1
  2998.     lsl.l    #8,d1
  2999.     move.b    14(a1),d1
  3000.     move.l    d1,(a0)+
  3001.  
  3002.     add.w    #16,a1
  3003.     dbf    d0,.loop
  3004.     move.l    a0,d2                ;save buffer ptr
  3005.     move.l    a3,d3                ;save buffer ptr
  3006.  
  3007.     CONVERT_POST
  3008.  
  3009.     lsr.l    #1,d0
  3010.     move.w    d0,AUD0LEN(a0)
  3011.     move.w    d0,AUD1LEN(a0)
  3012.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3013.     rts
  3014.  
  3015. *******************************************************************************
  3016.  
  3017. SoftInt_8bitSH:
  3018.     CONVERT_PRE
  3019.  
  3020.     move.l    d2,a0                ;get buffer ptr
  3021.     move.l    d3,a3                ;get buffer ptr
  3022. .loop
  3023.  
  3024. ; Left
  3025.     move.b    (a1),d1
  3026.     lsl.l    #8,d1
  3027.     move.b    8(a1),d1
  3028.     lsl.l    #8,d1
  3029.     move.b    16(a1),d1
  3030.     lsl.l    #8,d1
  3031.     move.b    24(a1),d1
  3032.     move.l    d1,(a3)+
  3033.  
  3034. ; Right
  3035.     move.b    4(a1),d1
  3036.     lsl.l    #8,d1
  3037.     move.b    12(a1),d1
  3038.     lsl.l    #8,d1
  3039.     move.b    20(a1),d1
  3040.     lsl.l    #8,d1
  3041.     move.b    28(a1),d1
  3042.     move.l    d1,(a0)+
  3043.  
  3044.     add.w    #32,a1
  3045.     dbf    d0,.loop
  3046.     move.l    a0,d2                ;save buffer ptr
  3047.     move.l    a3,d3                ;save buffer ptr
  3048.  
  3049.     CONVERT_POST
  3050.  
  3051.     lsr.l    #1,d0
  3052.     move.w    d0,AUD0LEN(a0)
  3053.     move.w    d0,AUD1LEN(a0)
  3054.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3055.     rts
  3056.  
  3057. *******************************************************************************
  3058.  
  3059. SoftInt_14bitM:
  3060.     CONVERT_PRE
  3061.  
  3062.     move.l    d2,a0                ;get buffer ptr
  3063.     move.l    d5,a5                ;get buffer ptr
  3064. .loop
  3065.  
  3066. ; High
  3067.     move.b    (a1),d1
  3068.     lsl.l    #8,d1
  3069.     move.b    2(a1),d1
  3070.     lsl.l    #8,d1
  3071.     move.b    4(a1),d1
  3072.     lsl.l    #8,d1
  3073.     move.b    6(a1),d1
  3074.     move.l    d1,(a0)+
  3075.  
  3076. ; Low
  3077.     move.b    1(a1),d1
  3078.     lsr.b    #2,d1
  3079.     lsl.l    #8,d1
  3080.     move.b    3(a1),d1
  3081.     lsr.b    #2,d1
  3082.     lsl.l    #8,d1
  3083.     move.b    5(a1),d1
  3084.     lsr.b    #2,d1
  3085.     lsl.l    #8,d1
  3086.     move.b    7(a1),d1
  3087.     lsr.b    #2,d1
  3088.     move.l    d1,(a5)+
  3089.  
  3090.     addq.w    #8,a1
  3091.     dbf    d0,.loop
  3092.     move.l    a0,d2                ;save buffer ptr
  3093.     move.l    a5,d5                ;save buffer ptr
  3094.  
  3095.     CONVERT_POST
  3096.  
  3097.     lsr.l    #1,d0
  3098.     move.w    d0,AUD0LEN(a0)
  3099.     move.w    d0,AUD1LEN(a0)
  3100.     move.w    d0,AUD2LEN(a0)
  3101.     move.w    d0,AUD3LEN(a0)
  3102.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3103.     rts
  3104.  
  3105. *******************************************************************************
  3106.  
  3107.  
  3108. SoftInt_14bitMH:
  3109.     CONVERT_PRE
  3110.  
  3111.     move.l    d2,a0                ;get buffer ptr
  3112.     move.l    d5,a5                ;get buffer ptr
  3113. .loop
  3114.  
  3115. ; High
  3116.     move.b    (a1),d1
  3117.     lsl.l    #8,d1
  3118.     move.b    4(a1),d1
  3119.     lsl.l    #8,d1
  3120.     move.b    8(a1),d1
  3121.     lsl.l    #8,d1
  3122.     move.b    12(a1),d1
  3123.     move.l    d1,(a0)+
  3124.  
  3125. ; Low
  3126.     move.b    1(a1),d1
  3127.     lsr.b    #2,d1
  3128.     lsl.l    #8,d1
  3129.     move.b    5(a1),d1
  3130.     lsr.b    #2,d1
  3131.     lsl.l    #8,d1
  3132.     move.b    9(a1),d1
  3133.     lsr.b    #2,d1
  3134.     lsl.l    #8,d1
  3135.     move.b    13(a1),d1
  3136.     lsr.b    #2,d1
  3137.     move.l    d1,(a5)+
  3138.  
  3139.     add.w    #16,a1
  3140.     dbf    d0,.loop
  3141.     move.l    a0,d2                ;save buffer ptr
  3142.     move.l    a5,d5                ;save buffer ptr
  3143.  
  3144.     CONVERT_POST
  3145.  
  3146.     lsr.l    #1,d0
  3147.     move.w    d0,AUD0LEN(a0)
  3148.     move.w    d0,AUD1LEN(a0)
  3149.     move.w    d0,AUD2LEN(a0)
  3150.     move.w    d0,AUD3LEN(a0)
  3151.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3152.     rts
  3153.  
  3154. *******************************************************************************
  3155.  
  3156. SoftInt_14CbitM:
  3157.     CONVERT_PRE
  3158.  
  3159.     move.l    d2,a0                ;get buffer ptr
  3160.     move.l    d5,a5                ;get buffer ptr
  3161.     move.l    p_CalibrationTable(a6),a3
  3162.     moveq    #0,d3
  3163. .loop
  3164.  
  3165.  IFGE    __CPU-68020
  3166.     move.w    (a1)+,d3
  3167.     move.w    (a3,d3.l*2),d3
  3168.  ELSE
  3169.     moveq    #0,d3
  3170.     move.w    (a1)+,d3
  3171.      add.w    d3,d3
  3172.      move.w    (a3,d3.l),d3
  3173.  ENDC
  3174.     move.b    d3,d1
  3175.     lsl.l    #8,d1                ;xxxxAAxx
  3176.     move.w    d3,d2
  3177.     lsl.l    #8,d2                ;xxaaxxxx
  3178.  IFGE    __CPU-68020
  3179.     move.w    (a1)+,d3
  3180.     move.w    (a3,d3.l*2),d3
  3181.  ELSE
  3182.     moveq    #0,d3
  3183.     move.w    (a1)+,d3
  3184.      add.w    d3,d3
  3185.      move.w    (a3,d3.l),d3
  3186.  ENDC
  3187.     move.b    d3,d1
  3188.     lsl.l    #8,d1                ;xxAABBxx
  3189.     move.w    d3,d2
  3190.     lsl.l    #8,d2                ;aabbxxxx
  3191.  IFGE    __CPU-68020
  3192.     move.w    (a1)+,d3
  3193.     move.w    (a3,d3.l*2),d3
  3194.  ELSE
  3195.     moveq    #0,d3
  3196.     move.w    (a1)+,d3
  3197.      add.w    d3,d3
  3198.      move.w    (a3,d3.l),d3
  3199.  ENDC
  3200.     move.b    d3,d1
  3201.     lsl.l    #8,d1                ;AABBCCxx
  3202.     move.w    d3,d2                ;aabbccxx
  3203.  
  3204.  IFGE    __CPU-68020
  3205.     move.w    (a1)+,d3
  3206.     move.w    (a3,d3.l*2),d3
  3207.  ELSE
  3208.     moveq    #0,d3
  3209.     move.w    (a1)+,d3
  3210.      add.w    d3,d3
  3211.      move.w    (a3,d3.l),d3
  3212.  ENDC
  3213.     move.b    d3,d1                ;AABBCCDD
  3214.     lsr.w    #8,d3
  3215.     move.b    d3,d2                ;aabbccdd
  3216.  
  3217.     move.l    d1,(a5)+
  3218.     move.l    d2,(a0)+
  3219.  
  3220.     dbf    d0,.loop
  3221.     move.l    a0,d2                ;save buffer ptr
  3222.     move.l    a5,d5                ;save buffer ptr
  3223.  
  3224.     CONVERT_POST
  3225.  
  3226.     lsr.l    #1,d0
  3227.     move.w    d0,AUD0LEN(a0)
  3228.     move.w    d0,AUD1LEN(a0)
  3229.     move.w    d0,AUD2LEN(a0)
  3230.     move.w    d0,AUD3LEN(a0)
  3231.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3232.     rts
  3233.  
  3234. *******************************************************************************
  3235.  
  3236. SoftInt_14CbitMH:
  3237.     CONVERT_PRE
  3238.  
  3239.     move.l    d2,a0                ;get buffer ptr
  3240.     move.l    d5,a5                ;get buffer ptr
  3241.     move.l    p_CalibrationTable(a6),a3
  3242.     moveq    #0,d3
  3243. .loop
  3244.  
  3245.  IFGE    __CPU-68020
  3246.     move.w    (a1),d3
  3247.     move.w    (a3,d3.l*2),d3
  3248.  ELSE
  3249.     moveq    #0,d3
  3250.     move.w    (a1),d3
  3251.      add.w    d3,d3
  3252.      move.w    (a3,d3.l),d3
  3253.  ENDC
  3254.     move.b    d3,d1
  3255.     lsl.l    #8,d1                ;xxxxAAxx
  3256.     move.w    d3,d2
  3257.     lsl.l    #8,d2                ;xxaaxxxx
  3258.  IFGE    __CPU-68020
  3259.     move.w    4(a1),d3
  3260.     move.w    (a3,d3.l*2),d3
  3261.  ELSE
  3262.     moveq    #0,d3
  3263.     move.w    4(a1),d3
  3264.      add.w    d3,d3
  3265.      move.w    (a3,d3.l),d3
  3266.  ENDC
  3267.     move.b    d3,d1
  3268.     lsl.l    #8,d1                ;xxAABBxx
  3269.     move.w    d3,d2
  3270.     lsl.l    #8,d2                ;aabbxxxx
  3271.  IFGE    __CPU-68020
  3272.     move.w    8(a1),d3
  3273.     move.w    (a3,d3.l*2),d3
  3274.  ELSE
  3275.     moveq    #0,d3
  3276.     move.w    8(a1),d3
  3277.      add.w    d3,d3
  3278.      move.w    (a3,d3.l),d3
  3279.  ENDC
  3280.     move.b    d3,d1
  3281.     lsl.l    #8,d1                ;AABBCCxx
  3282.     move.w    d3,d2                ;aabbccxx
  3283.  
  3284.  IFGE    __CPU-68020
  3285.     move.w    12(a1),d3
  3286.     move.w    (a3,d3.l*2),d3
  3287.  ELSE
  3288.     moveq    #0,d3
  3289.     move.w    12(a1),d3
  3290.      add.w    d3,d3
  3291.      move.w    (a3,d3.l),d3
  3292.  ENDC
  3293.     move.b    d3,d1                ;AABBCCDD
  3294.     lsr.w    #8,d3
  3295.     move.b    d3,d2                ;aabbccdd
  3296.  
  3297.     move.l    d1,(a5)+
  3298.     add.w    #16,a1
  3299.     move.l    d2,(a0)+
  3300.  
  3301.     dbf    d0,.loop
  3302.     move.l    a0,d2                ;save buffer ptr
  3303.     move.l    a5,d5                ;save buffer ptr
  3304.  
  3305.     CONVERT_POST
  3306.  
  3307.     lsr.l    #1,d0
  3308.     move.w    d0,AUD0LEN(a0)
  3309.     move.w    d0,AUD1LEN(a0)
  3310.     move.w    d0,AUD2LEN(a0)
  3311.     move.w    d0,AUD3LEN(a0)
  3312.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3313.     rts
  3314.  
  3315.  
  3316. *******************************************************************************
  3317.  
  3318. SoftInt_14bitS:
  3319.     CONVERT_PRE
  3320.  
  3321.     move.l    d2,a0                ;get buffer ptr
  3322.     move.l    d3,a3                ;get buffer ptr
  3323.     move.l    d4,a4                ;get buffer ptr
  3324.     move.l    d5,a5                ;get buffer ptr
  3325. .loop
  3326.  
  3327. ; Left High
  3328.     move.b    (a1),d1
  3329.     lsl.l    #8,d1
  3330.     move.b    4(a1),d1
  3331.     lsl.l    #8,d1
  3332.     move.b    8(a1),d1
  3333.     lsl.l    #8,d1
  3334.     move.b    12(a1),d1
  3335.     move.l    d1,(a3)+
  3336.  
  3337. ; Left Low
  3338.     move.b    1(a1),d1
  3339.     lsr.b    #2,d1
  3340.     lsl.l    #8,d1
  3341.     move.b    5(a1),d1
  3342.     lsr.b    #2,d1
  3343.     lsl.l    #8,d1
  3344.     move.b    9(a1),d1
  3345.     lsr.b    #2,d1
  3346.     lsl.l    #8,d1
  3347.     move.b    13(a1),d1
  3348.     lsr.b    #2,d1
  3349.     move.l    d1,(a4)+
  3350.  
  3351. ; Right High
  3352.     move.b    2(a1),d1
  3353.     lsl.l    #8,d1
  3354.     move.b    6(a1),d1
  3355.     lsl.l    #8,d1
  3356.     move.b    10(a1),d1
  3357.     lsl.l    #8,d1
  3358.     move.b    14(a1),d1
  3359.     move.l    d1,(a0)+
  3360.  
  3361. ; Right Low
  3362.     move.b    3(a1),d1
  3363.     lsr.b    #2,d1
  3364.     lsl.l    #8,d1
  3365.     move.b    7(a1),d1
  3366.     lsr.b    #2,d1
  3367.     lsl.l    #8,d1
  3368.     move.b    11(a1),d1
  3369.     lsr.b    #2,d1
  3370.     lsl.l    #8,d1
  3371.     move.b    15(a1),d1
  3372.     lsr.b    #2,d1
  3373.     move.l    d1,(a5)+
  3374.  
  3375.     add.w    #16,a1
  3376.     dbf    d0,.loop
  3377.     move.l    a0,d2                ;save buffer ptr
  3378.     move.l    a3,d3                ;save buffer ptr
  3379.     move.l    a4,d4                ;save buffer ptr
  3380.     move.l    a5,d5                ;save buffer ptr
  3381.  
  3382.     CONVERT_POST
  3383.  
  3384.     lsr.l    #1,d0
  3385.     move.w    d0,AUD0LEN(a0)
  3386.     move.w    d0,AUD1LEN(a0)
  3387.     move.w    d0,AUD2LEN(a0)
  3388.     move.w    d0,AUD3LEN(a0)
  3389.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3390.     rts
  3391.  
  3392. *******************************************************************************
  3393.  
  3394. SoftInt_14bitSH:
  3395.     CONVERT_PRE
  3396.  
  3397.     move.l    d2,a0                ;get buffer ptr
  3398.     move.l    d3,a3                ;get buffer ptr
  3399.     move.l    d4,a4                ;get buffer ptr
  3400.     move.l    d5,a5                ;get buffer ptr
  3401. .loop
  3402.  
  3403. ; Left High
  3404.     move.b    (a1),d1
  3405.     lsl.l    #8,d1
  3406.     move.b    8(a1),d1
  3407.     lsl.l    #8,d1
  3408.     move.b    16(a1),d1
  3409.     lsl.l    #8,d1
  3410.     move.b    24(a1),d1
  3411.     move.l    d1,(a3)+
  3412.  
  3413. ; Left Low
  3414.     move.b    1(a1),d1
  3415.     lsr.b    #2,d1
  3416.     lsl.l    #8,d1
  3417.     move.b    9(a1),d1
  3418.     lsr.b    #2,d1
  3419.     lsl.l    #8,d1
  3420.     move.b    17(a1),d1
  3421.     lsr.b    #2,d1
  3422.     lsl.l    #8,d1
  3423.     move.b    25(a1),d1
  3424.     lsr.b    #2,d1
  3425.     move.l    d1,(a4)+
  3426.  
  3427. ; Right High
  3428.     move.b    4(a1),d1
  3429.     lsl.l    #8,d1
  3430.     move.b    12(a1),d1
  3431.     lsl.l    #8,d1
  3432.     move.b    20(a1),d1
  3433.     lsl.l    #8,d1
  3434.     move.b    28(a1),d1
  3435.     move.l    d1,(a0)+
  3436.  
  3437. ; Right Low
  3438.     move.b    5(a1),d1
  3439.     lsr.b    #2,d1
  3440.     lsl.l    #8,d1
  3441.     move.b    13(a1),d1
  3442.     lsr.b    #2,d1
  3443.     lsl.l    #8,d1
  3444.     move.b    21(a1),d1
  3445.     lsr.b    #2,d1
  3446.     lsl.l    #8,d1
  3447.     move.b    29(a1),d1
  3448.     lsr.b    #2,d1
  3449.     move.l    d1,(a5)+
  3450.  
  3451.     add.w    #32,a1
  3452.     dbf    d0,.loop
  3453.     move.l    a0,d2                ;save buffer ptr
  3454.     move.l    a3,d3                ;save buffer ptr
  3455.     move.l    a4,d4                ;save buffer ptr
  3456.     move.l    a5,d5                ;save buffer ptr
  3457.  
  3458.     CONVERT_POST
  3459.  
  3460.     lsr.l    #1,d0
  3461.     move.w    d0,AUD0LEN(a0)
  3462.     move.w    d0,AUD1LEN(a0)
  3463.     move.w    d0,AUD2LEN(a0)
  3464.     move.w    d0,AUD3LEN(a0)
  3465.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3466.     rts
  3467.  
  3468.  
  3469. *******************************************************************************
  3470.  
  3471. SoftInt_14CbitS:
  3472.     CONVERT_PRE
  3473.  
  3474.     move.l    d2,a0                ;get buffer ptr
  3475.     move.l    d3,a3                ;get buffer ptr
  3476.     move.l    d4,a4                ;get buffer ptr
  3477.     move.l    d5,a5                ;get buffer ptr
  3478.     push    a6
  3479.     move.l    p_CalibrationTable(a6),a6
  3480.     moveq    #0,d3
  3481. .loop
  3482.  
  3483. ; Left
  3484.  IFGE    __CPU-68020
  3485.     move.w    (a1),d3
  3486.     move.w    (a6,d3.l*2),d3
  3487.  ELSE
  3488.     moveq    #0,d3
  3489.     move.w    (a1),d3
  3490.      add.w    d3,d3
  3491.      move.w    (a6,d3.l),d3
  3492.  ENDC
  3493.     move.b    d3,d1
  3494.     lsl.l    #8,d1                ;xxxxAAxx
  3495.     move.w    d3,d2
  3496.     lsl.l    #8,d2                ;xxaaxxxx
  3497.  IFGE    __CPU-68020
  3498.     move.w    4(a1),d3
  3499.     move.w    (a6,d3.l*2),d3
  3500.  ELSE
  3501.     moveq    #0,d3
  3502.     move.w    4(a1),d3
  3503.      add.w    d3,d3
  3504.      move.w    (a6,d3.l),d3
  3505.  ENDC
  3506.     move.b    d3,d1
  3507.     lsl.l    #8,d1                ;xxAABBxx
  3508.     move.w    d3,d2
  3509.     lsl.l    #8,d2                ;aabbxxxx
  3510.  IFGE    __CPU-68020
  3511.     move.w    8(a1),d3
  3512.     move.w    (a6,d3.l*2),d3
  3513.  ELSE
  3514.     moveq    #0,d3
  3515.     move.w    8(a1),d3
  3516.      add.w    d3,d3
  3517.      move.w    (a6,d3.l),d3
  3518.  ENDC
  3519.     move.b    d3,d1
  3520.     lsl.l    #8,d1                ;AABBCCxx
  3521.     move.w    d3,d2                ;aabbccxx
  3522.  
  3523.  IFGE    __CPU-68020
  3524.     move.w    12(a1),d3
  3525.     move.w    (a6,d3.l*2),d3
  3526.  ELSE
  3527.     moveq    #0,d3
  3528.     move.w    12(a1),d3
  3529.      add.w    d3,d3
  3530.      move.w    (a6,d3.l),d3
  3531.  ENDC
  3532.     move.b    d3,d1                ;AABBCCDD
  3533.     lsr.w    #8,d3
  3534.     move.b    d3,d2                ;aabbccdd
  3535.  
  3536.     move.l    d1,(a4)+
  3537.     move.l    d2,(a3)+
  3538.  
  3539. ; Right
  3540.  IFGE    __CPU-68020
  3541.     move.w    2(a1),d3
  3542.     move.w    (a6,d3.l*2),d3
  3543.  ELSE
  3544.     moveq    #0,d3
  3545.     move.w    2(a1),d3
  3546.      add.w    d3,d3
  3547.      move.w    (a6,d3.l),d3
  3548.  ENDC
  3549.     move.b    d3,d1
  3550.     lsl.l    #8,d1                ;xxxxAAxx
  3551.     move.w    d3,d2
  3552.     lsl.l    #8,d2                ;xxaaxxxx
  3553.  IFGE    __CPU-68020
  3554.     move.w    6(a1),d3
  3555.     move.w    (a6,d3.l*2),d3
  3556.  ELSE
  3557.     moveq    #0,d3
  3558.     move.w    6(a1),d3
  3559.      add.w    d3,d3
  3560.      move.w    (a6,d3.l),d3
  3561.  ENDC
  3562.     move.b    d3,d1
  3563.     lsl.l    #8,d1                ;xxAABBxx
  3564.     move.w    d3,d2
  3565.     lsl.l    #8,d2                ;aabbxxxx
  3566.  IFGE    __CPU-68020
  3567.     move.w    10(a1),d3
  3568.     move.w    (a6,d3.l*2),d3
  3569.  ELSE
  3570.     moveq    #0,d3
  3571.     move.w    10(a1),d3
  3572.      add.w    d3,d3
  3573.      move.w    (a6,d3.l),d3
  3574.  ENDC
  3575.     move.b    d3,d1
  3576.     lsl.l    #8,d1                ;AABBCCxx
  3577.     move.w    d3,d2                ;aabbccxx
  3578.  
  3579.  IFGE    __CPU-68020
  3580.     move.w    14(a1),d3
  3581.     move.w    (a6,d3.l*2),d3
  3582.  ELSE
  3583.     moveq    #0,d3
  3584.     move.w    14(a1),d3
  3585.      add.w    d3,d3
  3586.      move.w    (a6,d3.l),d3
  3587.  ENDC
  3588.     move.b    d3,d1                ;AABBCCDD
  3589.     lsr.w    #8,d3
  3590.     move.b    d3,d2                ;aabbccdd
  3591.  
  3592.     move.l    d1,(a5)+
  3593.     add.w    #16,a1
  3594.     move.l    d2,(a0)+
  3595.  
  3596.     dbf    d0,.loop
  3597.     pop    a6
  3598.     move.l    a0,d2                ;save buffer ptr
  3599.     move.l    a3,d3                ;save buffer ptr
  3600.     move.l    a4,d4                ;save buffer ptr
  3601.     move.l    a5,d5                ;save buffer ptr
  3602.  
  3603.     CONVERT_POST
  3604.  
  3605.     lsr.l    #1,d0
  3606.     move.w    d0,AUD0LEN(a0)
  3607.     move.w    d0,AUD1LEN(a0)
  3608.     move.w    d0,AUD2LEN(a0)
  3609.     move.w    d0,AUD3LEN(a0)
  3610.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3611.     rts
  3612.  
  3613.  
  3614. *******************************************************************************
  3615.  
  3616. SoftInt_14CbitSH:
  3617.     CONVERT_PRE
  3618.  
  3619.     move.l    d2,a0                ;get buffer ptr
  3620.     move.l    d3,a3                ;get buffer ptr
  3621.     move.l    d4,a4                ;get buffer ptr
  3622.     move.l    d5,a5                ;get buffer ptr
  3623.     push    a6
  3624.     move.l    p_CalibrationTable(a6),a6
  3625.     moveq    #0,d3
  3626. .loop
  3627.  
  3628. ; Left
  3629.  IFGE    __CPU-68020
  3630.     move.w    (a1),d3
  3631.     move.w    (a6,d3.l*2),d3
  3632.  ELSE
  3633.     moveq    #0,d3
  3634.     move.w    (a1),d3
  3635.      add.w    d3,d3
  3636.      move.w    (a6,d3.l),d3
  3637.  ENDC
  3638.     move.b    d3,d1
  3639.     lsl.l    #8,d1                ;xxxxAAxx
  3640.     move.w    d3,d2
  3641.     lsl.l    #8,d2                ;xxaaxxxx
  3642.  IFGE    __CPU-68020
  3643.     move.w    8(a1),d3
  3644.     move.w    (a6,d3.l*2),d3
  3645.  ELSE
  3646.     moveq    #0,d3
  3647.     move.w    8(a1),d3
  3648.      add.w    d3,d3
  3649.      move.w    (a6,d3.l),d3
  3650.  ENDC
  3651.     move.b    d3,d1
  3652.     lsl.l    #8,d1                ;xxAABBxx
  3653.     move.w    d3,d2
  3654.     lsl.l    #8,d2                ;aabbxxxx
  3655.  IFGE    __CPU-68020
  3656.     move.w    16(a1),d3
  3657.     move.w    (a6,d3.l*2),d3
  3658.  ELSE
  3659.     moveq    #0,d3
  3660.     move.w    16(a1),d3
  3661.      add.w    d3,d3
  3662.      move.w    (a6,d3.l),d3
  3663.  ENDC
  3664.     move.b    d3,d1
  3665.     lsl.l    #8,d1                ;AABBCCxx
  3666.     move.w    d3,d2                ;aabbccxx
  3667.  
  3668.  IFGE    __CPU-68020
  3669.     move.w    24(a1),d3
  3670.     move.w    (a6,d3.l*2),d3
  3671.  ELSE
  3672.     moveq    #0,d3
  3673.     move.w    24(a1),d3
  3674.      add.w    d3,d3
  3675.      move.w    (a6,d3.l),d3
  3676.  ENDC
  3677.     move.b    d3,d1                ;AABBCCDD
  3678.     lsr.w    #8,d3
  3679.     move.b    d3,d2                ;aabbccdd
  3680.  
  3681.     move.l    d1,(a4)+
  3682.     move.l    d2,(a3)+
  3683.  
  3684. ; Right
  3685.  IFGE    __CPU-68020
  3686.     move.w    4(a1),d3
  3687.     move.w    (a6,d3.l*2),d3
  3688.  ELSE
  3689.     moveq    #0,d3
  3690.     move.w    4(a1),d3
  3691.      add.w    d3,d3
  3692.      move.w    (a6,d3.l),d3
  3693.  ENDC
  3694.     move.b    d3,d1
  3695.     lsl.l    #8,d1                ;xxxxAAxx
  3696.     move.w    d3,d2
  3697.     lsl.l    #8,d2                ;xxaaxxxx
  3698.  IFGE    __CPU-68020
  3699.     move.w    12(a1),d3
  3700.     move.w    (a6,d3.l*2),d3
  3701.  ELSE
  3702.     moveq    #0,d3
  3703.     move.w    12(a1),d3
  3704.      add.w    d3,d3
  3705.      move.w    (a6,d3.l),d3
  3706.  ENDC
  3707.     move.b    d3,d1
  3708.     lsl.l    #8,d1                ;xxAABBxx
  3709.     move.w    d3,d2
  3710.     lsl.l    #8,d2                ;aabbxxxx
  3711.  IFGE    __CPU-68020
  3712.     move.w    20(a1),d3
  3713.     move.w    (a6,d3.l*2),d3
  3714.  ELSE
  3715.     moveq    #0,d3
  3716.     move.w    20(a1),d3
  3717.      add.w    d3,d3
  3718.      move.w    (a6,d3.l),d3
  3719.  ENDC
  3720.     move.b    d3,d1
  3721.     lsl.l    #8,d1                ;AABBCCxx
  3722.     move.w    d3,d2                ;aabbccxx
  3723.  
  3724.  IFGE    __CPU-68020
  3725.     move.w    28(a1),d3
  3726.     move.w    (a6,d3.l*2),d3
  3727.  ELSE
  3728.     moveq    #0,d3
  3729.     move.w    28(a1),d3
  3730.      add.w    d3,d3
  3731.      move.w    (a6,d3.l),d3
  3732.  ENDC
  3733.     move.b    d3,d1                ;AABBCCDD
  3734.     lsr.w    #8,d3
  3735.     move.b    d3,d2                ;aabbccdd
  3736.  
  3737.     move.l    d1,(a5)+
  3738.     add.w    #32,a1
  3739.     move.l    d2,(a0)+
  3740.  
  3741.     dbf    d0,.loop
  3742.     pop    a6
  3743.     move.l    a0,d2                ;save buffer ptr
  3744.     move.l    a3,d3                ;save buffer ptr
  3745.     move.l    a4,d4                ;save buffer ptr
  3746.     move.l    a5,d5                ;save buffer ptr
  3747.  
  3748.     CONVERT_POST
  3749.  
  3750.     lsr.l    #1,d0
  3751.     move.w    d0,AUD0LEN(a0)
  3752.     move.w    d0,AUD1LEN(a0)
  3753.     move.w    d0,AUD2LEN(a0)
  3754.     move.w    d0,AUD3LEN(a0)
  3755.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3756.     rts
  3757. EndCode:
  3758.